diff options
Diffstat (limited to 'moon-abe/pbc-0.5.14/arith/multiz.c')
-rw-r--r-- | moon-abe/pbc-0.5.14/arith/multiz.c | 589 |
1 files changed, 0 insertions, 589 deletions
diff --git a/moon-abe/pbc-0.5.14/arith/multiz.c b/moon-abe/pbc-0.5.14/arith/multiz.c deleted file mode 100644 index 6c8b43cc..00000000 --- a/moon-abe/pbc-0.5.14/arith/multiz.c +++ /dev/null @@ -1,589 +0,0 @@ -// Multinomials over Z. -// e.g. [[1, 2], 3, [4, [5, 6]]] means -// (1 + 2y) + 3 x + (4 + (5 + 6z)y)x^2 -// Convenient interchange format for different groups, rings, and fields. - -// TODO: Canonicalize, e.g. [[1]], 0, 0] --> 1. - -#include <stdarg.h> -#include <stdio.h> -#include <stdint.h> // for intptr_t -#include <stdlib.h> -#include <gmp.h> -#include "pbc_utils.h" -#include "pbc_field.h" -#include "pbc_multiz.h" -#include "pbc_random.h" -#include "pbc_fp.h" -#include "pbc_memory.h" -#include "misc/darray.h" - -// Per-element data. -struct multiz_s { - // Either it's an mpz, or a list of mpzs. - char type; - union { - mpz_t z; - darray_t a; - }; -}; - -enum { - T_MPZ, - T_ARR, -}; - -static multiz multiz_new_empty_list(void) { - multiz ep = pbc_malloc(sizeof(*ep)); - ep->type = T_ARR; - darray_init(ep->a); - return ep; -} - -void multiz_append(element_ptr x, element_ptr e) { - multiz l = x->data; - darray_append(l->a, e->data); -} - -static multiz multiz_new(void) { - multiz ep = pbc_malloc(sizeof(*ep)); - ep->type = T_MPZ; - mpz_init(ep->z); - return ep; -} - -static void f_init(element_ptr e) { - e->data = multiz_new(); -} - -static void multiz_free(multiz ep) { - switch(ep->type) { - case T_MPZ: - mpz_clear(ep->z); - break; - default: - PBC_ASSERT(T_ARR == ep->type, "no such type"); - darray_forall(ep->a, (void(*)(void*))multiz_free); - darray_clear(ep->a); - break; - } - pbc_free(ep); -} - -static void f_clear(element_ptr e) { - multiz_free(e->data); -} - -element_ptr multiz_new_list(element_ptr e) { - element_ptr x = pbc_malloc(sizeof(*x)); - element_init_same_as(x, e); - multiz_free(x->data); - x->data = multiz_new_empty_list(); - multiz_append(x, e); - return x; -} - -static void f_set_si(element_ptr e, signed long int op) { - multiz_free(e->data); - f_init(e); - multiz ep = e->data; - mpz_set_si(ep->z, op); -} - -static void f_set_mpz(element_ptr e, mpz_ptr z) { - multiz_free(e->data); - f_init(e); - multiz ep = e->data; - mpz_set(ep->z, z); -} - -static void f_set0(element_ptr e) { - multiz_free(e->data); - f_init(e); -} - -static void f_set1(element_ptr e) { - multiz_free(e->data); - f_init(e); - multiz ep = e->data; - mpz_set_ui(ep->z, 1); -} - -static size_t multiz_out_str(FILE *stream, int base, multiz ep) { - switch(ep->type) { - case T_MPZ: - return mpz_out_str(stream, base, ep->z); - default: - PBC_ASSERT(T_ARR == ep->type, "no such type"); - fputc('[', stream); - size_t res = 1; - int n = darray_count(ep->a); - int i; - for(i = 0; i < n; i++) { - if (i) res += 2, fputs(", ", stream); - res += multiz_out_str(stream, base, darray_at(ep->a, i)); - } - fputc(']', stream); - res++; - return res; - } -} - -static size_t f_out_str(FILE *stream, int base, element_ptr e) { - return multiz_out_str(stream, base, e->data); -} - -void multiz_to_mpz(mpz_ptr z, multiz ep) { - while(ep->type == T_ARR) ep = darray_at(ep->a, 0); - PBC_ASSERT(T_MPZ == ep->type, "no such type"); - mpz_set(z, ep->z); -} - -static void f_to_mpz(mpz_ptr z, element_ptr a) { - multiz_to_mpz(z, a->data); -} - -static int multiz_sgn(multiz ep) { - while(ep->type == T_ARR) ep = darray_at(ep->a, 0); - PBC_ASSERT(T_MPZ == ep->type, "no such type"); - return mpz_sgn(ep->z); -} - -static int f_sgn(element_ptr a) { - return multiz_sgn(a->data); -} - -static void add_to_x(void *data, - multiz x, - void (*fun)(mpz_t, const mpz_t, void *scope_ptr), - void *scope_ptr); - -static multiz multiz_new_unary(const multiz y, - void (*fun)(mpz_t, const mpz_t, void *scope_ptr), void *scope_ptr) { - multiz x = pbc_malloc(sizeof(*x)); - switch(y->type) { - case T_MPZ: - x->type = T_MPZ; - mpz_init(x->z); - fun(x->z, y->z, scope_ptr); - break; - default: - PBC_ASSERT(T_ARR == ep->type, "no such type"); - x->type = T_ARR; - darray_init(x->a); - darray_forall4(y->a, - (void(*)(void*,void*,void*,void*))add_to_x, - x, - fun, - scope_ptr); - break; - } - return x; -} - -static void add_to_x(void *data, - multiz x, - void (*fun)(mpz_t, const mpz_t, void *scope_ptr), - void *scope_ptr) { - darray_append(x->a, multiz_new_unary(data, fun, scope_ptr)); -} - -static void mpzset(mpz_t dst, const mpz_t src, void *scope_ptr) { - UNUSED_VAR(scope_ptr); - mpz_set(dst, src); -} - -static multiz multiz_clone(multiz y) { - return multiz_new_unary(y, (void(*)(mpz_t, const mpz_t, void *))mpzset, NULL); -} - -static multiz multiz_new_bin(const multiz a, const multiz b, - void (*fun)(mpz_t, const mpz_t, const mpz_t)) { - if (T_MPZ == a->type) { - if (T_MPZ == b->type) { - multiz x = multiz_new(); - fun(x->z, a->z, b->z); - return x; - } else { - multiz x = multiz_clone(b); - multiz z = x; - PBC_ASSERT(T_ARR == z->type, "no such type"); - while(z->type == T_ARR) z = darray_at(z->a, 0); - fun(z->z, a->z, z->z); - return x; - } - } else { - PBC_ASSERT(T_ARR == a->type, "no such type"); - if (T_MPZ == b->type) { - multiz x = multiz_clone(a); - multiz z = x; - PBC_ASSERT(T_ARR == z->type, "no such type"); - while(z->type == T_ARR) z = darray_at(z->a, 0); - fun(z->z, b->z, z->z); - return x; - } else { - PBC_ASSERT(T_ARR == b->type, "no such type"); - int m = darray_count(a->a); - int n = darray_count(b->a); - int min = m < n ? m : n; - int max = m > n ? m : n; - multiz x = multiz_new_empty_list(); - int i; - for(i = 0; i < min; i++) { - multiz z = multiz_new_bin(darray_at(a->a, i), darray_at(b->a, i), fun); - darray_append(x->a, z); - } - multiz zero = multiz_new(); - for(; i < max; i++) { - multiz z = multiz_new_bin(m > n ? darray_at(a->a, i) : zero, - n > m ? darray_at(b->a, i) : zero, - fun); - darray_append(x->a, z); - } - multiz_free(zero); - return x; - } - } -} -static multiz multiz_new_add(const multiz a, const multiz b) { - return multiz_new_bin(a, b, mpz_add); -} - -static void f_add(element_ptr n, element_ptr a, element_ptr b) { - multiz delme = n->data; - n->data = multiz_new_add(a->data, b->data); - multiz_free(delme); -} - -static multiz multiz_new_sub(const multiz a, const multiz b) { - return multiz_new_bin(a, b, mpz_sub); -} -static void f_sub(element_ptr n, element_ptr a, element_ptr b) { - multiz delme = n->data; - n->data = multiz_new_sub(a->data, b->data); - multiz_free(delme); -} - -static void mpzmul(mpz_t x, const mpz_t y, const mpz_t z) { - mpz_mul(x, y, z); -} - -static multiz multiz_new_mul(const multiz a, const multiz b) { - if (T_MPZ == a->type) { - // Multiply each coefficient of b by a->z. - return multiz_new_unary(b, (void(*)(mpz_t, const mpz_t, void *))mpzmul, a->z); - } else { - PBC_ASSERT(T_ARR == a->type, "no such type"); - if (T_MPZ == b->type) { - // Multiply each coefficient of a by b->z. - return multiz_new_unary(a, (void(*)(mpz_t, const mpz_t, void *))mpzmul, b->z); - } else { - PBC_ASSERT(T_ARR == b->type, "no such type"); - int m = darray_count(a->a); - int n = darray_count(b->a); - int max = m + n - 1; - multiz x = multiz_new_empty_list(); - int i; - multiz zero = multiz_new(); - for(i = 0; i < max; i++) { - multiz z = multiz_new(); - int j; - for (j = 0; j <= i; j++) { - multiz y = multiz_new_mul(j < m ? darray_at(a->a, j) : zero, - i - j < n ? darray_at(b->a, i - j) : zero); - multiz t = multiz_new_add(z, y); - multiz_free(y); - multiz_free(z); - z = t; - } - darray_append(x->a, z); - } - multiz_free(zero); - return x; - } - } -} -static void f_mul(element_ptr n, element_ptr a, element_ptr b) { - multiz delme = n->data; - n->data = multiz_new_mul(a->data, b->data); - multiz_free(delme); -} - -static void f_mul_mpz(element_ptr n, element_ptr a, mpz_ptr z) { - multiz delme = n->data; - n->data = multiz_new_unary(a->data, (void(*)(mpz_t, const mpz_t, void *))mpzmul, z); - multiz_free(delme); -} - -static void mulsi(mpz_t x, const mpz_t y, signed long *i) { - mpz_mul_si(x, y, *i); -} - -static void f_mul_si(element_ptr n, element_ptr a, signed long int z) { - multiz delme = n->data; - n->data = multiz_new_unary(a->data, (void(*)(mpz_t, const mpz_t, void *))mulsi, &z); - multiz_free(delme); -} - -static void mpzneg(mpz_t dst, const mpz_t src, void *scope_ptr) { - UNUSED_VAR(scope_ptr); - mpz_neg(dst, src); -} - -static multiz multiz_new_neg(multiz z) { - return multiz_new_unary(z, (void(*)(mpz_t, const mpz_t, void *))mpzneg, NULL); -} - -static void f_set(element_ptr n, element_ptr a) { - multiz delme = n->data; - n->data = multiz_clone(a->data); - multiz_free(delme); -} - -static void f_neg(element_ptr n, element_ptr a) { - multiz delme = n->data; - n->data = multiz_new_neg(a->data); - multiz_free(delme); -} - -static void f_div(element_ptr c, element_ptr a, element_ptr b) { - mpz_t d; - mpz_init(d); - element_to_mpz(d, b); - multiz delme = c->data; - c->data = multiz_new_unary(a->data, (void(*)(mpz_t, const mpz_t, void *))mpz_tdiv_q, d); - mpz_clear(d); - multiz_free(delme); -} - -// Doesn't make sense if order is infinite. -static void f_random(element_ptr n) { - multiz delme = n->data; - f_init(n); - multiz_free(delme); -} - -static void f_from_hash(element_ptr n, void *data, int len) { - mpz_t z; - mpz_init(z); - mpz_import(z, len, -1, 1, -1, 0, data); - f_set_mpz(n, z); - mpz_clear(z); -} - -static int f_is1(element_ptr n) { - multiz ep = n->data; - return ep->type == T_MPZ && !mpz_cmp_ui(ep->z, 1); -} - -int multiz_is0(multiz m) { - return m->type == T_MPZ && mpz_is0(m->z); -} - -static int f_is0(element_ptr n) { - return multiz_is0(n->data); -} - -static int f_item_count(element_ptr e) { - multiz z = e->data; - if (T_MPZ == z->type) return 0; - return darray_count(z->a); -} - -// TODO: Redesign multiz so this doesn't leak. -static element_ptr f_item(element_ptr e, int i) { - multiz z = e->data; - if (T_MPZ == z->type) return NULL; - element_ptr r = malloc(sizeof(*r)); - r->field = e->field; - r->data = darray_at(z->a, i); - return r; -} - -// Usual meaning when both are integers. -// Otherwise, compare coefficients. -static int multiz_cmp(multiz a, multiz b) { - if (T_MPZ == a->type) { - if (T_MPZ == b->type) { - // Simplest case: both are integers. - return mpz_cmp(a->z, b->z); - } - // Leading coefficient of b. - while(T_ARR == b->type) b = darray_last(b->a); - PBC_ASSERT(T_MPZ == b->type, "no such type"); - return -mpz_sgn(b->z); - } - PBC_ASSERT(T_ARR == a->type, "no such type"); - if (T_MPZ == b->type) { - // Leading coefficient of a. - while(T_ARR == a->type) a = darray_last(a->a); - PBC_ASSERT(T_MPZ == a->type, "no such type"); - return mpz_sgn(a->z); - } - PBC_ASSERT(T_ARR == b->type, "no such type"); - int m = darray_count(a->a); - int n = darray_count(b->a); - if (m > n) { - // Leading coefficient of a. - while(T_ARR == a->type) a = darray_last(a->a); - PBC_ASSERT(T_MPZ == a->type, "no such type"); - return mpz_sgn(a->z); - } - if (n > m) { - // Leading coefficient of b. - while(T_ARR == b->type) b = darray_last(b->a); - PBC_ASSERT(T_MPZ == b->type, "no such type"); - return -mpz_sgn(b->z); - } - for(n--; n >= 0; n--) { - int i = multiz_cmp(darray_at(a->a, n), darray_at(b->a, n)); - if (i) return i; - } - return 0; -} -static int f_cmp(element_ptr x, element_ptr y) { - return multiz_cmp(x->data, y->data); -} - -static void f_field_clear(field_t f) { UNUSED_VAR (f); } - -// OpenSSL convention: -// 4 bytes containing length -// followed by number in big-endian, most-significant bit set if negative -// (prepending null byte if necessary) -// Positive numbers also the same as mpz_out_raw. -static int z_to_bytes(unsigned char *data, element_t e) { - mpz_ptr z = e->data; - size_t msb = mpz_sizeinbase(z, 2); - size_t n = 4; - size_t i; - - if (!(msb % 8)) { - data[4] = 0; - n++; - } - if (mpz_sgn(z) < 0) { - mpz_export(data + n, NULL, 1, 1, 1, 0, z); - data[4] |= 128; - } else { - mpz_export(data + n, NULL, 1, 1, 1, 0, z); - } - n += (msb + 7) / 8 - 4; - for (i=0; i<4; i++) { - data[i] = (n >> 8 * (3 - i)); - } - n += 4; - - return n; -} - -static int z_from_bytes(element_t e, unsigned char *data) { - unsigned char *ptr; - size_t i, n; - mpz_ptr z = e->data; - mpz_t z1; - int neg = 0; - - mpz_init(z1); - mpz_set_ui(z, 0); - - ptr = data; - n = 0; - for (i=0; i<4; i++) { - n += ((unsigned int) *ptr) << 8 * (3 - i); - ptr++; - } - if (data[4] & 128) { - neg = 1; - data[4] &= 127; - } - for (i=0; i<n; i++) { - mpz_set_ui(z1, *ptr); - mpz_mul_2exp(z1, z1, 8 * (n - 1 - i)); - ptr++; - mpz_add(z, z, z1); - } - mpz_clear(z1); - if (neg) mpz_neg(z, z); - return n; -} - -static int z_length_in_bytes(element_ptr a) { - return (mpz_sizeinbase(a->data, 2) + 7) / 8 + 4; -} - -static void f_out_info(FILE *out, field_ptr f) { - UNUSED_VAR(f); - fprintf(out, "Z multinomials"); -} - -static int f_set_str(element_ptr e, const char *s, int base) { - // TODO: Square brackets. - mpz_t z; - mpz_init(z); - int result = pbc_mpz_set_str(z, s, base); - f_set_mpz(e, z); - mpz_clear(z); - return result; -} - -static void f_set_multiz(element_ptr e, multiz m) { - multiz delme = e->data; - e->data = multiz_clone(m); - multiz_free(delme); -} - -void field_init_multiz(field_ptr f) { - field_init(f); - f->init = f_init; - f->clear = f_clear; - f->set_si = f_set_si; - f->set_mpz = f_set_mpz; - f->set_multiz = f_set_multiz; - f->set_str = f_set_str; - f->out_str = f_out_str; - f->sign = f_sgn; - f->add = f_add; - f->sub = f_sub; - f->set = f_set; - f->mul = f_mul; - f->mul_mpz = f_mul_mpz; - f->mul_si = f_mul_si; - f->neg = f_neg; - f->cmp = f_cmp; - f->div = f_div; - f->random = f_random; - f->from_hash = f_from_hash; - f->is1 = f_is1; - f->is0 = f_is0; - f->set0 = f_set0; - f->set1 = f_set1; - f->field_clear = f_field_clear; - f->to_bytes = z_to_bytes; - f->from_bytes = z_from_bytes; - f->to_mpz = f_to_mpz; - f->length_in_bytes = z_length_in_bytes; - f->item = f_item; - f->item_count = f_item_count; - - f->out_info = f_out_info; - - mpz_set_ui(f->order, 0); - f->data = NULL; - f->fixed_length_in_bytes = -1; -} - -int multiz_is_z(multiz m) { - return T_MPZ == m->type; -} - -int multiz_count(multiz m) { - if (T_ARR != m->type) return -1; - return darray_count(m->a); -} - -multiz multiz_at(multiz m, int i) { - PBC_ASSERT(T_ARR == m->type, "wrong type"); - PBC_ASSERT(darray_count(m->a) > i, "out of bounds"); - return darray_at(m->a, i); -} |