basic prng functionality with seeding via cli argument
This commit is contained in:
parent
833f548d5d
commit
421cace0c7
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "extern/pcg"]
|
||||||
|
path = extern/pcg
|
||||||
|
url = https://github.com/imneme/pcg-c-basic.git
|
|
@ -9,15 +9,20 @@ project(
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED TRUE)
|
set(CMAKE_C_STANDARD_REQUIRED TRUE)
|
||||||
|
|
||||||
|
set(XTEST_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
option(XTEST_ENABLE_PRNG "enable prng functions" ON)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
set(XTEST_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
|
|
||||||
function(add_xtest_executable TARGET)
|
function(add_xtest_executable TARGET)
|
||||||
add_executable(${TARGET} ${ARGN})
|
add_executable(${TARGET} ${ARGN})
|
||||||
target_compile_definitions(${TARGET} PRIVATE XTEST)
|
set(XTEST_COMPILE_DEFS XTEST)
|
||||||
|
if (XTEST_ENABLE_PRNG)
|
||||||
|
set(XTEST_COMPILE_DEFS ${XTEST_COMPILE_DEFS} XTEST_PRNG)
|
||||||
|
endif ()
|
||||||
|
target_compile_definitions(${TARGET} PRIVATE ${XTEST_COMPILE_DEFS})
|
||||||
target_include_directories(${TARGET} AFTER PRIVATE "${XTEST_SOURCE_DIR}/include/xtest")
|
target_include_directories(${TARGET} AFTER PRIVATE "${XTEST_SOURCE_DIR}/include/xtest")
|
||||||
target_include_directories(${TARGET} SYSTEM BEFORE PRIVATE "${XTEST_SOURCE_DIR}/include/xtest-assert")
|
target_include_directories(${TARGET} SYSTEM BEFORE PRIVATE "${XTEST_SOURCE_DIR}/include/xtest-assert")
|
||||||
target_link_libraries(${TARGET} xtest)
|
target_link_libraries(${TARGET} xtest)
|
||||||
|
|
|
@ -2,19 +2,20 @@ function(xtest_define_example NAME)
|
||||||
set(TARGET_NAME "example-${NAME}")
|
set(TARGET_NAME "example-${NAME}")
|
||||||
add_xtest_executable(${TARGET_NAME} source.c ${NAME}.c ${ARGN})
|
add_xtest_executable(${TARGET_NAME} source.c ${NAME}.c ${ARGN})
|
||||||
if (NAME STREQUAL "all")
|
if (NAME STREQUAL "all")
|
||||||
target_compile_definitions(${TARGET_NAME} PRIVATE XTEST_ALL_EXAMPLES)
|
set(EXAMPLE_COMPILE_DEFINITIONS ${EXAMPLE_COMPILE_DEFINITIONS} XTEST_ALL_EXAMPLES)
|
||||||
endif ()
|
endif ()
|
||||||
|
target_compile_definitions(${TARGET_NAME} PRIVATE ${EXAMPLE_COMPILE_DEFINITIONS})
|
||||||
target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic)
|
target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
if (XTEST_BUILD_EXAMPLES)
|
if (XTEST_BUILD_EXAMPLES)
|
||||||
xtest_define_example(all assertions.c expect_assertions.c fail.c float.c groups.c parameterized.c skip.c)
|
xtest_define_example(all assertions.c expect_assertions.c fail.c float.c groups.c parameterized.c prng.c skip.c)
|
||||||
xtest_define_example(assertions)
|
xtest_define_example(assertions)
|
||||||
xtest_define_example(expect_assertions)
|
xtest_define_example(expect_assertions)
|
||||||
xtest_define_example(fail)
|
xtest_define_example(fail)
|
||||||
xtest_define_example(float)
|
xtest_define_example(float)
|
||||||
xtest_define_example(groups)
|
xtest_define_example(groups)
|
||||||
xtest_define_example(parameterized)
|
xtest_define_example(parameterized)
|
||||||
|
xtest_define_example(prng)
|
||||||
xtest_define_example(skip)
|
xtest_define_example(skip)
|
||||||
endif ()
|
endif ()
|
17
examples/prng.c
Normal file
17
examples/prng.c
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include "xtest.h"
|
||||||
|
#include "source.h"
|
||||||
|
|
||||||
|
|
||||||
|
void rand_int() {
|
||||||
|
int a = xtest_rand_int();
|
||||||
|
int b = xtest_rand_int();
|
||||||
|
int res = a + b;
|
||||||
|
xtest_assert_is(add(a, b), res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef XTEST_ALL_EXAMPLES
|
||||||
|
XTEST_MAIN {
|
||||||
|
xtest_run(rand_int);
|
||||||
|
}
|
||||||
|
#endif
|
1
extern/pcg
vendored
Submodule
1
extern/pcg
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit bc39cd76ac3d541e618606bcc6e1e5ba5e5e6aa3
|
|
@ -15,9 +15,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef void (*xtest_test_fn)(void *fixture, void **params);
|
typedef void (*xtest_test_fn)(void * fixture, void ** params);
|
||||||
typedef void (*xtest_setup_fn)(void **fixture);
|
typedef void (*xtest_setup_fn)(void ** fixture);
|
||||||
typedef void (*xtest_teardown_fn)(void *fixture);
|
typedef void (*xtest_teardown_fn)(void * fixture);
|
||||||
|
|
||||||
typedef struct xtest_param_s xtest_param;
|
typedef struct xtest_param_s xtest_param;
|
||||||
|
|
||||||
|
@ -48,17 +48,15 @@ enum xtest_type {
|
||||||
xtest_type_other,
|
xtest_type_other,
|
||||||
};
|
};
|
||||||
|
|
||||||
void xtest_init(int argc, char **argv);
|
void xtest_init(int argc, char**argv);
|
||||||
|
|
||||||
void xtest_fail_assert(const char *expression, const char *file, int line, void *expected,
|
void xtest_fail_assert(const char *expression, const char *file, int line, void *expected,
|
||||||
void *actual, _Bool invert, enum xtest_type type);
|
void *actual, _Bool invert, enum xtest_type type);
|
||||||
void
|
void
|
||||||
xtest_assert_float(double expected, double actual, int precision, _Bool invert, const char *expression,
|
xtest_assert_float(double expected, double actual, int precision, _Bool invert, const char *expression, const char *file,
|
||||||
const char *file,
|
|
||||||
int line);
|
int line);
|
||||||
|
|
||||||
void xtest_assert_mem(const char *expected, const char *actual, size_t length, _Bool invert, const char *expression,
|
void xtest_assert_mem(const char *expected, const char *actual, size_t length, _Bool invert, const char *expression, const char *file,
|
||||||
const char *file,
|
|
||||||
int line);
|
int line);
|
||||||
|
|
||||||
void xtest_internal_run(xtest_test_fn fn, const char *name, xtest_param *params, xtest_setup_fn setup,
|
void xtest_internal_run(xtest_test_fn fn, const char *name, xtest_param *params, xtest_setup_fn setup,
|
||||||
|
@ -71,6 +69,18 @@ void xtest_skip(const char *reason);
|
||||||
void xtest_expect_assertion_failure();
|
void xtest_expect_assertion_failure();
|
||||||
int xtest_complete();
|
int xtest_complete();
|
||||||
|
|
||||||
|
#ifdef XTEST_PRNG
|
||||||
|
void xtest_rand_fill(char* buf, size_t len);
|
||||||
|
double xtest_rand_double();
|
||||||
|
double xtest_rand_double_range(double min, double max);
|
||||||
|
int xtest_rand_int();
|
||||||
|
int xtest_rand_int_range(int min, int max);
|
||||||
|
uint8_t xtest_rand_8();
|
||||||
|
uint16_t xtest_rand_16();
|
||||||
|
uint32_t xtest_rand_32();
|
||||||
|
uint64_t xtest_rand_64();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define xtest_run(fn) xtest_internal_run(fn, #fn, (void*)0, (void*)0, (void*)0)
|
#define xtest_run(fn) xtest_internal_run(fn, #fn, (void*)0, (void*)0, (void*)0)
|
||||||
#define xtest_run_parameterized(fn, params) xtest_internal_run(fn, #fn, params, (void*)0, (void*)0)
|
#define xtest_run_parameterized(fn, params) xtest_internal_run(fn, #fn, params, (void*)0, (void*)0)
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
|
|
||||||
add_library(xtest xtest.c)
|
if(XTEST_ENABLE_PRNG)
|
||||||
target_compile_definitions(xtest PRIVATE XTEST)
|
set(XTEST_ADDITIONAL_SOURCES ${XTEST_SOURCE_DIR}/extern/pcg/pcg_basic.c)
|
||||||
|
set(XTEST_ADDITIONAL_DEFINES XTEST_PRNG)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(xtest xtest.c ${XTEST_ADDITIONAL_SOURCES})
|
||||||
|
target_compile_definitions(xtest PRIVATE XTEST ${XTEST_ADDITIONAL_DEFINES})
|
||||||
target_compile_options(xtest PRIVATE -Wall -Wextra -pedantic)
|
target_compile_options(xtest PRIVATE -Wall -Wextra -pedantic)
|
||||||
target_include_directories(xtest PRIVATE ../extern/pcg ../include/xtest)
|
target_include_directories(xtest PRIVATE ${XTEST_SOURCE_DIR}/extern/pcg ${XTEST_SOURCE_DIR}/include/xtest)
|
||||||
|
|
||||||
|
|
206
src/xtest.c
206
src/xtest.c
|
@ -7,7 +7,21 @@
|
||||||
#include "xtest.h"
|
#include "xtest.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef XTEST_PRNG
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "pcg_basic.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XTEST_PRNG
|
||||||
|
#define PRNG_SEED_LENGTH 22
|
||||||
|
pcg32_random_t rng;
|
||||||
|
typedef char prng_seed[PRNG_SEED_LENGTH + 1];
|
||||||
|
void xtest_rand_init(prng_seed seed);
|
||||||
|
#endif
|
||||||
|
|
||||||
struct xtest_assert_info {
|
struct xtest_assert_info {
|
||||||
const char *file;
|
const char *file;
|
||||||
|
@ -63,14 +77,18 @@ _Bool list_tests = 0;
|
||||||
|
|
||||||
|
|
||||||
#define USAGE_BASE "[-?|--help] [-l|--list] [-m|--match filter] [-f|--output-format format]"
|
#define USAGE_BASE "[-?|--help] [-l|--list] [-m|--match filter] [-f|--output-format format]"
|
||||||
|
#define USAGE_PRNG "[-s|--seed prng-seed]"
|
||||||
|
|
||||||
#define USAGE_HELP_LIST "-l|--list list the available tests"
|
#define USAGE_HELP_LIST "-l|--list list the available tests"
|
||||||
#define USAGE_HELP_MATCH "-m|--match filter only run/list tests whose name matches the filter"
|
#define USAGE_HELP_MATCH "-m|--match filter only run/list tests whose name matches the filter"
|
||||||
#define USAGE_HELP_FORMAT "-f|--output-format format specify the output format; supported formats are \"default\" and \"subunit\""
|
#define USAGE_HELP_FORMAT "-f|--output-format format specify the output format; supported formats are \"default\" and \"subunit\""
|
||||||
|
#define USAGE_HELP_SEED "-s|--seed prng-seed specify a seed for the prng"
|
||||||
#define USAGE_HELP_HELP "-?|--help show this message"
|
#define USAGE_HELP_HELP "-?|--help show this message"
|
||||||
|
#ifdef XTEST_PRNG
|
||||||
|
#define USAGE "Usage: %s " USAGE_BASE " " USAGE_PRNG "\n " USAGE_HELP_LIST "\n " USAGE_HELP_MATCH "\n " USAGE_HELP_FORMAT "\n " USAGE_HELP_SEED "\n " USAGE_HELP_HELP
|
||||||
|
#else
|
||||||
#define USAGE "Usage: %s " USAGE_BASE "\n " USAGE_HELP_LIST "\n " USAGE_HELP_MATCH "\n " USAGE_HELP_FORMAT "\n " USAGE_HELP_HELP
|
#define USAGE "Usage: %s " USAGE_BASE "\n " USAGE_HELP_LIST "\n " USAGE_HELP_MATCH "\n " USAGE_HELP_FORMAT "\n " USAGE_HELP_HELP
|
||||||
|
#endif
|
||||||
|
|
||||||
static _Noreturn void usage(const char *progname) {
|
static _Noreturn void usage(const char *progname) {
|
||||||
printf(USAGE, progname);
|
printf(USAGE, progname);
|
||||||
|
@ -111,6 +129,10 @@ void xtest_init(int argc, char **argv) {
|
||||||
int list_flag = 0;
|
int list_flag = 0;
|
||||||
int help_flag = 0;
|
int help_flag = 0;
|
||||||
const char *format = NULL;
|
const char *format = NULL;
|
||||||
|
#ifdef XTEST_PRNG
|
||||||
|
const char *seed_arg = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *progname = argv[0];
|
const char *progname = argv[0];
|
||||||
|
|
||||||
struct option long_options[] =
|
struct option long_options[] =
|
||||||
|
@ -119,6 +141,9 @@ void xtest_init(int argc, char **argv) {
|
||||||
{"help", no_argument, &help_flag, 1}, // list the tests instead of running them
|
{"help", no_argument, &help_flag, 1}, // list the tests instead of running them
|
||||||
{"match", required_argument, 0, 'm'}, // only run tests that match the provided filter
|
{"match", required_argument, 0, 'm'}, // only run tests that match the provided filter
|
||||||
{"output-format", required_argument, 0, 'f'}, // select output format
|
{"output-format", required_argument, 0, 'f'}, // select output format
|
||||||
|
#ifdef XTEST_PRNG
|
||||||
|
{"seed", required_argument, 0, 's'}, // provide a prng seed
|
||||||
|
#endif
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -138,6 +163,11 @@ void xtest_init(int argc, char **argv) {
|
||||||
case 'f':
|
case 'f':
|
||||||
format = optarg;
|
format = optarg;
|
||||||
break;
|
break;
|
||||||
|
#ifdef XTEST_PRNG
|
||||||
|
case 's':
|
||||||
|
seed_arg = optarg;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case '?':
|
case '?':
|
||||||
help_flag = 1;
|
help_flag = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -164,6 +194,15 @@ void xtest_init(int argc, char **argv) {
|
||||||
printf("invalid output format '%s', allowed formats are 'default' and 'subunit'\n", format);
|
printf("invalid output format '%s', allowed formats are 'default' and 'subunit'\n", format);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XTEST_PRNG
|
||||||
|
char seed[PRNG_SEED_LENGTH + 1] = {0};
|
||||||
|
if (seed_arg != NULL) {
|
||||||
|
snprintf(seed, PRNG_SEED_LENGTH + 1, "%s", seed_arg);
|
||||||
|
}
|
||||||
|
xtest_rand_init(seed);
|
||||||
|
printf("[PRNG seed: %s]\n============\n", seed);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -480,3 +519,166 @@ void xtest_internal_end_group() {
|
||||||
void xtest_expect_assertion_failure() {
|
void xtest_expect_assertion_failure() {
|
||||||
expecting_assertion = 1;
|
expecting_assertion = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XTEST_PRNG
|
||||||
|
|
||||||
|
|
||||||
|
#define SEED_ENC_0 2
|
||||||
|
#define SEED_ENC_A 12
|
||||||
|
#define SEED_ENC_a 38
|
||||||
|
|
||||||
|
|
||||||
|
union seed_encode_box {
|
||||||
|
struct {
|
||||||
|
uint64_t state;
|
||||||
|
uint64_t seq;
|
||||||
|
};
|
||||||
|
uint8_t bytes[PRNG_SEED_LENGTH * 6 / 8 + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
void encode_seed(prng_seed seed, uint64_t state, uint64_t seq) {
|
||||||
|
union seed_encode_box box;
|
||||||
|
memset(&box, 0, sizeof(box));
|
||||||
|
box.state = state;
|
||||||
|
box.seq = seq;
|
||||||
|
uint8_t cur;
|
||||||
|
for (int i = 0; i < PRNG_SEED_LENGTH; i += 1) {
|
||||||
|
switch (i % 4) {
|
||||||
|
case 0:
|
||||||
|
cur = box.bytes[i * 6 / 8] & 0x3F;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
cur = (box.bytes[i * 6 / 8] >> 6) | ((box.bytes[i * 6 / 8 + 1] & 0xF) << 2);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
cur = (box.bytes[i * 6 / 8] >> 4) | ((box.bytes[i * 6 / 8 + 1] & 0x3) << 4);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
cur = (box.bytes[i * 6 / 8] >> 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char c;
|
||||||
|
if (cur == 0) c = '_';
|
||||||
|
else if (cur == 1) c = '.';
|
||||||
|
else if (cur >= SEED_ENC_0 && cur <= SEED_ENC_0 + '9' - '0') c = (char) (cur - SEED_ENC_0 + '0');
|
||||||
|
else if (cur >= SEED_ENC_A && cur <= SEED_ENC_A + 'Z' - 'A') c = (char) (cur - SEED_ENC_A + 'A');
|
||||||
|
else if (cur >= SEED_ENC_a && cur <= SEED_ENC_a + 'z' - 'a') c = (char) (cur - SEED_ENC_a + 'a');
|
||||||
|
else
|
||||||
|
assert(0);
|
||||||
|
seed[i] = c;
|
||||||
|
}
|
||||||
|
seed[PRNG_SEED_LENGTH] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_seed(const prng_seed seed, uint64_t *state, uint64_t *seq) {
|
||||||
|
union seed_encode_box box;
|
||||||
|
memset(&box, 0, sizeof(box));
|
||||||
|
uint8_t cur;
|
||||||
|
for (int i = 0; i < PRNG_SEED_LENGTH; i += 1) {
|
||||||
|
char c = seed[i];
|
||||||
|
if (c == '_') cur = 0;
|
||||||
|
else if (c == '.') cur = 1;
|
||||||
|
else if (c >= '0' && c <= '9') cur = SEED_ENC_0 + c - '0';
|
||||||
|
else if (c >= 'A' && c <= 'Z') cur = SEED_ENC_A + c - 'A';
|
||||||
|
else if (c >= 'a' && c <= 'z') cur = SEED_ENC_a + c - 'a';
|
||||||
|
else cur = -1; // invalid seed character is just ignored and set to 0xFF so no error handling is necessary
|
||||||
|
switch (i % 4) {
|
||||||
|
case 0:
|
||||||
|
box.bytes[i * 6 / 8] |= cur;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
box.bytes[i * 6 / 8] |= cur << 6;
|
||||||
|
box.bytes[i * 6 / 8 + 1] |= cur >> 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
box.bytes[i * 6 / 8] |= cur << 4;
|
||||||
|
box.bytes[i * 6 / 8 + 1] |= cur >> 4;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
box.bytes[i * 6 / 8] |= cur << 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*state = box.state;
|
||||||
|
*seq = box.seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xtest_rand_init(prng_seed seed) {
|
||||||
|
uint64_t state;
|
||||||
|
uint64_t seq;
|
||||||
|
if (seed[0] == '\0') {
|
||||||
|
int64_t t = time(NULL);
|
||||||
|
int shift = (int) (t & 0x3F);
|
||||||
|
if (t >> 6 & 0x1) shift = -shift;
|
||||||
|
t = t >> 7;
|
||||||
|
|
||||||
|
t = t << shift | t >> (64 - shift);
|
||||||
|
|
||||||
|
state = (intptr_t) &printf ^ (intptr_t) seed << 32 ^ t;
|
||||||
|
seq = (intptr_t) &longjmp << 32 ^ (intptr_t) &xtest_rand_init ^ (t << 32 | t >> 32);
|
||||||
|
// state = time(NULL) ^ (intptr_t) &printf << 32 ^ (intptr_t) &time;
|
||||||
|
// seq = time(NULL) << 32 ^ (intptr_t) seed ^ (intptr_t) &matches << 32;
|
||||||
|
encode_seed(seed, state, seq);
|
||||||
|
} else {
|
||||||
|
decode_seed(seed, &state, &seq);
|
||||||
|
}
|
||||||
|
pcg32_srandom_r(&rng, state, seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xtest_rand_fill(char *buf, size_t len) {
|
||||||
|
uint32_t rand = 0;
|
||||||
|
for (size_t i = 0; i < len; ++i) {
|
||||||
|
if (i % 4 == 0) {
|
||||||
|
rand = pcg32_random_r(&rng);
|
||||||
|
}
|
||||||
|
buf[i] = (char) (rand >> (8 * (i % 4)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double xtest_rand_double() {
|
||||||
|
return ldexp((double) (xtest_rand_64() & 0xFFFFFFFFFFFFF), -52);
|
||||||
|
}
|
||||||
|
|
||||||
|
double xtest_rand_double_range(double min, double max) {
|
||||||
|
assert(min < max);
|
||||||
|
return (max - min) * xtest_rand_double() + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xtest_rand_int() {
|
||||||
|
uint32_t uval = pcg32_random_r(&rng);
|
||||||
|
int32_t *ival;
|
||||||
|
ival = (int32_t *) &uval;
|
||||||
|
return (int) *ival;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xtest_rand_int_range(int min, int max) {
|
||||||
|
int bound = max - min;
|
||||||
|
uint32_t uval = pcg32_boundedrand_r(&rng, bound);
|
||||||
|
int32_t *ival;
|
||||||
|
ival = (int32_t *) &uval;
|
||||||
|
return (int) *ival + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t xtest_rand_8() {
|
||||||
|
return (uint8_t) pcg32_random_r(&rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t xtest_rand_16() {
|
||||||
|
return (uint16_t) pcg32_random_r(&rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t xtest_rand_32() {
|
||||||
|
return pcg32_random_r(&rng);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t xtest_rand_64() {
|
||||||
|
uint32_t l = pcg32_random_r(&rng);
|
||||||
|
uint32_t h = pcg32_random_r(&rng);
|
||||||
|
return ((uint64_t) h) << 32 | l;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue