summaryrefslogtreecommitdiffstats
path: root/moon-abe/pbc-0.5.14/arith/tinyfp.c
diff options
context:
space:
mode:
Diffstat (limited to 'moon-abe/pbc-0.5.14/arith/tinyfp.c')
-rw-r--r--moon-abe/pbc-0.5.14/arith/tinyfp.c304
1 files changed, 304 insertions, 0 deletions
diff --git a/moon-abe/pbc-0.5.14/arith/tinyfp.c b/moon-abe/pbc-0.5.14/arith/tinyfp.c
new file mode 100644
index 00000000..50e883e1
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/arith/tinyfp.c
@@ -0,0 +1,304 @@
+// F_p for small p, i.e. at most sizeof(long) bytes long.
+// Assumes long long is at least twice long.
+
+// TODO: Fix outstanding bugs and use in PBC.
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h> // for intptr_t
+#include <stdlib.h>
+#include <string.h>
+#include <gmp.h>
+#include "pbc_utils.h"
+#include "pbc_field.h"
+#include "pbc_random.h"
+#include "pbc_fp.h"
+#include "pbc_memory.h"
+
+// Mostly wrappers. We use GMP routines for pow_mpz and invert.
+
+static void fp_init(element_ptr e) {
+ unsigned long *p = e->data = pbc_malloc(sizeof(unsigned long));
+ *p = 0;
+}
+
+static void fp_clear(element_ptr e) {
+ pbc_free(e->data);
+}
+
+static void fp_set_mpz(element_ptr e, mpz_ptr z) {
+ mpz_t r;
+ mpz_init(r);
+ unsigned long *p = e->field->data;
+ unsigned long *l = e->data;
+ mpz_fdiv_r_ui(r, z, *p);
+ *l = mpz_get_ui(r);
+ mpz_clear(r);
+}
+
+static void fp_set_si(element_ptr e, signed long int op) {
+ unsigned long int *d = e->data;
+ unsigned long *p = e->field->data;
+ if (op < 0) {
+ *d = (-op) % *p;
+ *d = *p - *d;
+ } else {
+ *d = op % *p;
+ }
+}
+
+static void fp_to_mpz(mpz_ptr z, element_ptr e) {
+ unsigned long int *l = e->data;
+ mpz_set_ui(z, *l);
+}
+
+static void fp_set0(element_ptr e) {
+ unsigned long int *l = e->data;
+ *l = 0;
+}
+
+static void fp_set1(element_ptr e) {
+ unsigned long int *l = e->data;
+ *l = 1;
+}
+
+static int fp_is1(element_ptr e) {
+ unsigned long int *l = e->data;
+ return *l == 1;
+}
+
+static int fp_is0(element_ptr e) {
+ unsigned long int *l = e->data;
+ return *l == 0;
+}
+
+static size_t fp_out_str(FILE *stream, int base, element_ptr e) {
+ size_t result;
+ mpz_t z;
+ mpz_init(z);
+ fp_to_mpz(z, e);
+ result = mpz_out_str(stream, base, z);
+ mpz_clear(z);
+ return result;
+}
+
+static void fp_add(element_ptr c, element_ptr a, element_ptr b) {
+ unsigned long *prime = a->field->data;
+ unsigned long *p = a->data;
+ unsigned long *q = b->data;
+ unsigned long *r = c->data;
+ unsigned long l0;
+ l0 = *p + *q;
+ if (l0 < *p) {
+ //overflow
+ l0 -= *prime;
+ }
+ *r = l0 % *prime;
+}
+
+static void fp_double(element_ptr c, element_ptr a) {
+ unsigned long *prime = a->field->data;
+ unsigned long *p = a->data;
+ unsigned long *r = c->data;
+ *r = 2 * *p;
+ if (*r < *p) {
+ //overflow
+ *r -= *prime;
+ }
+ *r = *r % *prime;
+}
+
+static void fp_sub(element_ptr c, element_ptr a, element_ptr b) {
+ unsigned long *prime = a->field->data;
+ unsigned long *p = a->data;
+ unsigned long *q = b->data;
+ unsigned long *r = c->data;
+
+ if (*p >= *q) {
+ *r = *p - *q;
+ } else {
+ *r = *prime - *q + *p;
+ }
+}
+
+static void fp_mul(element_ptr c, element_ptr a, element_ptr b) {
+ unsigned long *prime = a->field->data;
+ unsigned long *p = a->data;
+ unsigned long *q = b->data;
+ unsigned long long ll;
+ unsigned long *r = c->data;
+
+ ll = *p * *q;
+ *r = ll % *prime;
+}
+
+static void fp_square(element_ptr c, element_ptr a) {
+ fp_mul(c, a, a);
+}
+
+static void fp_neg(element_ptr c, element_ptr a) {
+ unsigned long *prime = a->field->data;
+ unsigned long *r = c->data;
+ unsigned long *p = a->data;
+ if (*p) {
+ *r = *prime - *p;
+ } else {
+ *r = 0;
+ }
+}
+
+static void fp_mul_si(element_ptr c, element_ptr a, signed long int op) {
+ unsigned long *prime = a->field->data;
+ unsigned long *p = a->data;
+ unsigned long long ll;
+ unsigned long *r = c->data;
+
+ ll = *p * op;
+ *r = ll % *prime;
+}
+
+static void fp_pow_mpz(element_ptr c, element_ptr a, mpz_ptr op) {
+ unsigned long *r = c->data;
+ mpz_t z;
+ mpz_init(z);
+ fp_to_mpz(z, a);
+ mpz_powm(z, z, op, a->field->order);
+ *r = mpz_get_ui(z);
+ mpz_clear(z);
+}
+
+static void fp_set(element_ptr c, element_ptr a) {
+ unsigned long *p = a->data;
+ unsigned long *r = c->data;
+ *r = *p;
+}
+
+static void fp_invert(element_ptr c, element_ptr a) {
+ unsigned long *r = c->data;
+ mpz_t z;
+ mpz_init(z);
+ fp_to_mpz(z, a);
+ mpz_invert(z, z, a->field->order);
+ *r = mpz_get_ui(z);
+ mpz_clear(z);
+}
+
+static void fp_random(element_ptr c) {
+ unsigned long *r = c->data;
+ mpz_t z;
+ mpz_init(z);
+ pbc_mpz_random(z, c->field->order);
+ *r = mpz_get_ui(z);
+ mpz_clear(z);
+}
+
+static void fp_from_hash(element_ptr n, void *data, int len) {
+ mpz_t z;
+
+ mpz_init(z);
+ mpz_import(z, len, -1, 1, -1, 0, data);
+ fp_set_mpz(n, z);
+ mpz_clear(z);
+}
+
+static int fp_cmp(element_ptr a, element_ptr b) {
+ unsigned long *p = a->data;
+ unsigned long *q = b->data;
+ return *p != *q;
+}
+
+static int fp_sgn_odd(element_ptr a) {
+ unsigned long *p = a->data;
+ if (!*p) return 0;
+ return *p & 1 ? 1 : -1;
+}
+
+static int fp_is_sqr(element_ptr a) {
+ int res;
+ mpz_t z;
+ mpz_init(z);
+ //0 is a square
+ if (fp_is0(a)) return 1;
+ fp_to_mpz(z, a);
+ res = mpz_legendre(z, a->field->order) == 1;
+ mpz_clear(z);
+ return res;
+}
+
+static int fp_to_bytes(unsigned char *data, element_t e) {
+ unsigned long *p = e->data;
+ unsigned long l = *p;
+ int i, n = e->field->fixed_length_in_bytes;
+ for (i = 0; i < n; i++) {
+ data[n - i - 1] = (unsigned char) l;
+ l >>= 8;
+ }
+ return n;
+}
+
+static int fp_from_bytes(element_t e, unsigned char *data) {
+ unsigned char *ptr = data;
+ unsigned long *p = e->data;
+ int i, n = e->field->fixed_length_in_bytes;
+ *p = 0;
+ for (i=0; i<n; i++) {
+ *p <<= 8;
+ *p += *ptr;
+ ptr++;
+ }
+ return n;
+}
+
+static void fp_field_clear(field_t f) {
+ pbc_free(f->data);
+}
+
+void field_init_tiny_fp(field_ptr f, mpz_t prime) {
+ unsigned long *p;
+
+ PBC_ASSERT(mpz_fits_ulong_p(prime), "modulus too big");
+
+ field_init(f);
+ f->init = fp_init;
+ f->clear = fp_clear;
+ f->set_si = fp_set_si;
+ f->set_mpz = fp_set_mpz;
+ f->out_str = fp_out_str;
+ f->add = fp_add;
+ f->sub = fp_sub;
+ f->set = fp_set;
+ f->mul = fp_mul;
+ f->mul_si = fp_mul_si;
+ f->square = fp_square;
+ f->doub = fp_double;
+ f->pow_mpz = fp_pow_mpz;
+ f->neg = fp_neg;
+ f->cmp = fp_cmp;
+ f->sign = fp_sgn_odd;
+ f->invert = fp_invert;
+ f->random = fp_random;
+ f->from_hash = fp_from_hash;
+ f->is1 = fp_is1;
+ f->is0 = fp_is0;
+ f->set0 = fp_set0;
+ f->set1 = fp_set1;
+ f->is_sqr = fp_is_sqr;
+ f->sqrt = element_tonelli;
+ f->field_clear = fp_field_clear;
+ f->to_bytes = fp_to_bytes;
+ f->from_bytes = fp_from_bytes;
+ f->to_mpz = fp_to_mpz;
+
+ p = f->data = pbc_malloc(sizeof(long));
+ *p = mpz_get_ui(prime);
+ {
+ unsigned long int l = 255;
+ f->fixed_length_in_bytes = 1;
+ while (l < *p) {
+ f->fixed_length_in_bytes++;
+ l <<= 8;
+ l += 255;
+ }
+ }
+ mpz_set(f->order, prime);
+}