// Inversion is slower than in a naive Fp implementation because of an extra // multiplication. // Requires nonzero a. static void fp_invert(element_ptr c, element_ptr a) { eptr ad = (eptr)a->data; eptr cd = (eptr)c->data; fptr p = (fptr)a->field->data; #ifdef _MSC_VER // for VC++ compatibility mp_limb_t tmp[MAX_LIMBS]; #else mp_limb_t tmp[p->limbs]; #endif mpz_t z; mpz_init(z); // Copy the limbs into a regular mpz_t so we can invert using the standard // mpz_invert(). mpz_import(z, p->limbs, -1, sizeof(mp_limb_t), 0, 0, ad->d); mpz_invert(z, z, a->field->order); set_limbs(tmp, z, p->limbs); // Normalize. mont_mul(cd->d, tmp, p->R3, p); cd->flag = 2; mpz_clear(z); }
void setup() { set_limbs(0); set_race_size(2); set_long("Un animal salvaje.\n"); set_name("animal"); set_short("Animal"); set_light_limits(LHUMANL, LHUMANH); set_playable(0); }
static void fp_set_mpz(element_ptr e, mpz_ptr z) { fptr p = (fptr)e->field->data; eptr ep = (eptr)e->data; if (!mpz_sgn(z)) ep->flag = 0; else { mpz_t tmp; mpz_init(tmp); mpz_mul_2exp(tmp, z, p->bytes * 8); mpz_mod(tmp, tmp, e->field->order); if (!mpz_sgn(tmp)) ep->flag = 0; else { set_limbs(ep->d, tmp, p->limbs); ep->flag = 2; } mpz_clear(tmp); } }
static void fp_random(element_ptr a) { fptr p = (fptr)a->field->data; eptr ad = (eptr)a->data; mpz_t z; mpz_init(z); pbc_mpz_random(z, a->field->order); if (mpz_sgn(z)) { mpz_mul_2exp(z, z, p->bytes * 8); mpz_mod(z, z, a->field->order); set_limbs(ad->d, z, p->limbs); ad->flag = 2; } else { ad->flag = 0; } mpz_clear(z); }
static void fp_pow_mpz(element_ptr c, element_ptr a, mpz_ptr op) { // Alternative: rewrite GMP mpz_powm(). fptr p = (fptr)a->field->data; eptr ad = (eptr)a->data; eptr cd = (eptr)c->data; if (!ad->flag) cd->flag = 0; else { mpz_t z; mpz_init(z); fp_to_mpz(z, a); mpz_powm(z, z, op, a->field->order); mpz_mul_2exp(z, z, p->bytes * 8); mpz_mod(z, z, a->field->order); set_limbs(cd->d, z, p->limbs); mpz_clear(z); cd->flag = 2; } }
static void fp_set_si(element_ptr e, signed long int op) { fptr p = (fptr)e->field->data; eptr ep = (eptr)e->data; if (!op) ep->flag = 0; else { mpz_t tmp; mpz_init(tmp); // TODO: Could be optimized. mpz_set_si(tmp, op); mpz_mul_2exp(tmp, tmp, p->bytes * 8); mpz_mod(tmp, tmp, e->field->order); if (!mpz_sgn(tmp)) ep->flag = 0; else { set_limbs(ep->d, tmp, p->limbs); ep->flag = 2; } mpz_clear(tmp); } }
static int fp_from_bytes(element_t a, unsigned char *data) { fptr p = (fptr)a->field->data; eptr ad = (eptr)a->data; int n; mpz_t z; mpz_init(z); n = a->field->fixed_length_in_bytes; mpz_import(z, n, 1, 1, 1, 0, data); if (!mpz_sgn(z)) ad->flag = 0; else { ad->flag = 2; mpz_mul_2exp(z, z, p->bytes * 8); mpz_mod(z, z, a->field->order); set_limbs(ad->d, z, p->limbs); } mpz_clear(z); return n; }
void field_init_mont_fp(field_ptr f, mpz_t prime) { PBC_ASSERT(!mpz_fits_ulong_p(prime), "modulus too small"); fptr p; 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->snprint = fp_snprint; f->set_str = fp_set_str; f->add = fp_add; f->sub = fp_sub; f->set = fp_set; f->mul = fp_mul; f->doub = fp_double; f->halve = fp_halve; f->pow_mpz = fp_pow_mpz; f->neg = fp_neg; f->sign = fp_sgn_odd; f->cmp = fp_cmp; 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; f->out_info = fp_out_info; // Initialize per-field data specific to this implementation. f->data = pbc_malloc(sizeof(*p)); p = (fptr)f->data; p->limbs = mpz_size(prime); p->bytes = p->limbs * sizeof(mp_limb_t); p->primelimbs = (mp_limb_t*)pbc_malloc(p->bytes); mpz_export(p->primelimbs, &p->limbs, -1, sizeof(mp_limb_t), 0, 0, prime); mpz_set(f->order, prime); f->fixed_length_in_bytes = (mpz_sizeinbase(prime, 2) + 7) / 8; // Compute R, R3 and negpinv. mpz_t z; mpz_init(z); p->R = (mp_limb_t*)pbc_malloc(p->bytes); p->R3 = (mp_limb_t*)pbc_malloc(p->bytes); mpz_setbit(z, p->bytes * 8); mpz_mod(z, z, prime); set_limbs(p->R, z, p->limbs); mpz_powm_ui(z, z, 3, prime); set_limbs(p->R3, z, p->limbs); mpz_set_ui(z, 0); // Algorithm II.5 in Blake, Seroussi and Smart is better but this suffices // since we're only doing it once. mpz_setbit(z, p->bytes * 8); mpz_invert(z, prime, z); #ifdef _MSC_VER // for VC++ compatibility int tmp = mpz_get_ui(z); p->negpinv = -tmp; #else p->negpinv = -mpz_get_ui(z); #endif mpz_clear(z); }