summaryrefslogtreecommitdiffstats
path: root/moon-abe/pbc-0.5.14/arith/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'moon-abe/pbc-0.5.14/arith/random.c')
-rw-r--r--moon-abe/pbc-0.5.14/arith/random.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/moon-abe/pbc-0.5.14/arith/random.c b/moon-abe/pbc-0.5.14/arith/random.c
new file mode 100644
index 00000000..68228b3f
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/arith/random.c
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <stdint.h> // for intptr_t
+#include <stdlib.h>
+#include <gmp.h>
+#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);
+}