/* See: * (1) Kaltofen, Valente, Yui 1989 * (2) Valente 1992 (Thesis) * (3) Konstantinou, Stamatiou, and Zaroliagis (CHES 2002) * This code is performing table 1 of reference 3. */ static void weber_root_to_hilbert_root(mpz_t r, mpz_t N, long D) { mpz_t A, t; if (D < 0) D = -D; D = ((D % 4) == 0) ? D/4 : D; if ( (D % 8) == 0 ) return; mpz_init(A); mpz_init(t); switch (D % 8) { case 1: if ((D % 3) != 0) mpz_powm_ui(t, r, 12, N); else mpz_powm_ui(t, r, 4, N); mpz_mul_ui(A, t, 64); mpz_sub_ui(t, A, 16); break; case 2: case 6: if ((D % 3) != 0) mpz_powm_ui(t, r, 12, N); else mpz_powm_ui(t, r, 4, N); mpz_mul_ui(A, t, 64); mpz_add_ui(t, A, 16); break; case 5: if ((D % 3) != 0) mpz_powm_ui(t, r, 6, N); else mpz_powm_ui(t, r, 2, N); mpz_mul_ui(A, t, 64); mpz_sub_ui(t, A, 16); break; case 7: if (!mpz_invert(t, r, N)) mpz_set_ui(t, 0); if ((D % 3) != 0) mpz_powm_ui(A, t, 24, N); else mpz_powm_ui(A, t, 8, N); mpz_sub_ui(t, A, 16); break; /* Results in degree 3x Hilbert, so typically not used */ case 3: if (!mpz_invert(t, r, N)) mpz_set_ui(t, 0); if ((D % 3) != 0) { mpz_powm_ui(t, t, 24, N); mpz_mul_2exp(A, t, 12); } else { mpz_powm_ui(t, t, 8, N); mpz_mul_2exp(A, t, 4); } mpz_sub_ui(t, A, 16); break; default: break; } /* r = t^3 / A */ mpz_powm_ui(t, t, 3, N); if ( ! mpz_divmod(r, t, A, N, r) ) mpz_set_ui(r, 0); mpz_clear(A); mpz_clear(t); }
static void select_curve_params(mpz_t a, mpz_t b, mpz_t g, long D, mpz_t *roots, long i, mpz_t N, mpz_t t) { int N_is_not_1_congruent_3; mpz_set_ui(a, 0); mpz_set_ui(b, 0); if (D == -3) { mpz_set_si(b, -1); } else if (D == -4) { mpz_set_si(a, -1); } else { mpz_sub_ui(t, roots[i], 1728); mpz_mod(t, t, N); /* c = (j * inverse(j-1728)) mod n */ if (mpz_divmod(b, roots[i], t, N, b)) { mpz_mul_si(a, b, -3); /* r = -3c */ mpz_mul_si(b, b, 2); /* s = 2c */ } } mpz_mod(a, a, N); mpz_mod(b, b, N); /* g: 1 < g < Ni && (g/Ni) != -1 && (g%3!=1 || cubic non-residue) */ N_is_not_1_congruent_3 = ! mpz_congruent_ui_p(N, 1, 3); for ( mpz_set_ui(g, 2); mpz_cmp(g, N) < 0; mpz_add_ui(g, g, 1) ) { if (mpz_jacobi(g, N) != -1) continue; if (N_is_not_1_congruent_3) break; mpz_sub_ui(t, N, 1); mpz_tdiv_q_ui(t, t, 3); mpz_powm(t, g, t, N); /* t = g^((Ni-1)/3) mod Ni */ if (mpz_cmp_ui(t, 1) == 0) continue; if (D == -3) { mpz_powm_ui(t, t, 3, N); if (mpz_cmp_ui(t, 1) != 0) /* Additional check when D == -3 */ continue; } break; } if (mpz_cmp(g, N) >= 0) /* No g can be found: N is composite */ mpz_set_ui(g, 0); }
extern void _jl_mpz_divmod(mpz_t* rop1, mpz_t* rop2, mpz_t* op1, mpz_t* op2) { mpz_divmod(*rop1, *rop2, *op1, *op2); }
void gmpint_divmodz(mpz_t *r, mpz_t *q, mpz_t *op, mpz_t *op2) { mpz_divmod(*r, *q, *op, *op2); }
static void mpz_mod_inverse(MP_INT *x, MP_INT *a, MP_INT *n) { MP_INT g0, g1, v0, v1, div, mod, aux; mpz_init_set(&g0, n); mpz_init_set(&g1, a); mpz_init_set_ui(&v0, 0); mpz_init_set_ui(&v1, 1); mpz_init(&div); mpz_init(&mod); mpz_init(&aux); while (mpz_cmp_ui(&g1, 0) != 0) { mpz_divmod(&div, &mod, &g0, &g1); mpz_mul(&aux, &div, &v1); mpz_sub(&aux, &v0, &aux); mpz_set(&v0, &v1); mpz_set(&v1, &aux); mpz_set(&g0, &g1); mpz_set(&g1, &mod); } if (mpz_cmp_ui(&v0, 0) < 0) mpz_add(x, &v0, n); else mpz_set(x, &v0); mpz_clear(&g0); mpz_clear(&g1); mpz_clear(&v0); mpz_clear(&v1); mpz_clear(&div); mpz_clear(&mod); mpz_clear(&aux); }
num_t num_float_two_op(optype_t op_type, num_t a, num_t b) { num_t r, r_z, rem_z, a_z, b_z; int both_z = num_both_z(a, b); r = num_new_fp(N_TEMP, NULL); mpfr_set_prec(F(r), num_max_prec(a, b)); a = num_new_fp(N_TEMP, a); b = num_new_fp(N_TEMP, b); if (both_z) { r_z = num_new_z(N_TEMP, NULL); rem_z = num_new_z(N_TEMP, NULL); a_z = num_new_z(N_TEMP, a); b_z = num_new_z(N_TEMP, b); } switch (op_type) { case OP_ADD: if (both_z) { mpz_add(Z(r_z), Z(a_z), Z(b_z)); return r_z; } else { mpfr_add(F(r), F(a), F(b), round_mode); } break; case OP_SUB: if (both_z) { mpz_sub(Z(r_z), Z(a_z), Z(b_z)); return r_z; } else { mpfr_sub(F(r), F(a), F(b), round_mode); } break; case OP_MUL: if (both_z) { mpz_mul(Z(r_z), Z(a_z), Z(b_z)); return r_z; } else { mpfr_mul(F(r), F(a), F(b), round_mode); } break; case OP_DIV: if (both_z) mpz_divmod(Z(r_z), Z(rem_z), Z(a_z), Z(b_z)); if (both_z && num_is_zero(rem_z)) return r_z; else mpfr_div(F(r), F(a), F(b), round_mode); break; case OP_MOD: if (both_z) { mpz_mod(Z(r_z), Z(a_z), Z(b_z)); return r_z; } else { /* * XXX: mpfr_fmod or mpfr_remainder */ mpfr_fmod(F(r), F(a), F(b), round_mode); } break; case OP_POW: mpfr_pow(F(r), F(a), F(b), round_mode); break; default: yyxerror("Unknown op in num_float_two_op"); } return r; }