#include #include // for intptr_t #include #include #include "pbc_random.h" #include "pbc_utils.h" #include "pbc_memory.h" void pbc_init_random(void); // Must use pointer due to lack of gmp_randstate_ptr. static gmp_randstate_t *get_rs(void) { static int rs_is_ready; static gmp_randstate_t rs; if (!rs_is_ready) { gmp_randinit_default(rs); rs_is_ready = 1; } return &rs; } static void deterministic_mpz_random(mpz_t z, mpz_t limit, void *data) { UNUSED_VAR (data); mpz_urandomm(z, *get_rs(), limit); } static void file_mpz_random(mpz_t r, mpz_t limit, void *data) { char *filename = (char *) data; FILE *fp; int n, bytecount, leftover; unsigned char *bytes; mpz_t z; mpz_init(z); fp = fopen(filename, "rb"); if (!fp) return; n = mpz_sizeinbase(limit, 2); bytecount = (n + 7) / 8; leftover = n % 8; bytes = (unsigned char *) pbc_malloc(bytecount); for (;;) { if (!fread(bytes, 1, bytecount, fp)) { pbc_warn("error reading source of random bits"); return; } if (leftover) { *bytes = *bytes % (1 << leftover); } mpz_import(z, bytecount, 1, 1, 0, 0, bytes); if (mpz_cmp(z, limit) < 0) break; } fclose(fp); mpz_set(r, z); mpz_clear(z); pbc_free(bytes); } static void (*current_mpz_random)(mpz_t, mpz_t, void *); static void *current_random_data; static int random_function_ready = 0; void pbc_random_set_function(void (*fun)(mpz_t, mpz_t, void *), void *data) { current_mpz_random = fun; current_random_data = data; random_function_ready = 1; } void pbc_mpz_random(mpz_t z, mpz_t limit) { if (!random_function_ready) pbc_init_random(); current_mpz_random(z, limit, current_random_data); } void pbc_mpz_randomb(mpz_t z, unsigned int bits) { mpz_t limit; mpz_init(limit); mpz_setbit(limit, bits); pbc_mpz_random(z, limit); mpz_clear(limit); } void pbc_random_set_deterministic(unsigned int seed) { gmp_randseed_ui(*get_rs(), seed); pbc_random_set_function(deterministic_mpz_random, NULL); } void pbc_random_set_file(char *filename) { pbc_random_set_function(file_mpz_random, filename); }