void hypgeom_precompute(hypgeom_t hyp) { if (fmpz_poly_is_one(hyp->A) && fmpz_poly_is_one(hyp->B)) { _hypgeom_precompute(hyp, hyp->P, hyp->Q); } else { fmpz_poly_t P2, Q2; fmpz_poly_init(P2); fmpz_poly_init(Q2); hypgeom_standardize(P2, Q2, hyp->A, hyp->B, hyp->P, hyp->Q); _hypgeom_precompute(hyp, P2, Q2); { fmpz_t t; fmpz_init(t); fmpz_poly_evaluate_si(t, hyp->A, 0); mag_mul_fmpz(hyp->MK, hyp->MK, t); fmpz_poly_evaluate_si(t, hyp->B, 0); mag_div_fmpz(hyp->MK, hyp->MK, t); fmpz_clear(t); } fmpz_poly_clear(P2); fmpz_poly_clear(Q2); } }
void fmpz_poly_q_canonicalise(fmpz_poly_q_t rop) { fmpz_poly_t gcd; if (fmpz_poly_is_zero(rop->den)) { flint_printf("Exception (fmpz_poly_q_canonicalise). Denominator is zero.\n"); abort(); } if (fmpz_poly_is_one(rop->den)) return; fmpz_poly_init(gcd); fmpz_poly_gcd(gcd, rop->num, rop->den); if (!fmpz_poly_is_unit(gcd)) { fmpz_poly_div(rop->num, rop->num, gcd); fmpz_poly_div(rop->den, rop->den, gcd); } fmpz_poly_clear(gcd); if (fmpz_sgn(fmpz_poly_lead(rop->den)) < 0) { fmpz_poly_neg(rop->num, rop->num); fmpz_poly_neg(rop->den, rop->den); } }
/** * \ingroup StringConversions * * Returns the string representation of the rational function \c op. */ char * fmpz_poly_q_get_str(const fmpz_poly_q_t op) { int i, j; char * str; char * numstr; char * denstr; if (fmpz_poly_is_one(op->den)) { numstr = fmpz_poly_get_str(op->num); i = strlen(numstr) - 1; if (numstr[i] == ' ') { numstr[i] = '\0'; } return numstr; } numstr = fmpz_poly_get_str(op->num); denstr = fmpz_poly_get_str(op->den); i = strlen(numstr) - 1; if (numstr[i] == ' ') numstr[i] = '\0'; i = strlen(denstr) - 1; if (denstr[i] == ' ') denstr[i] = '\0'; str = flint_malloc(strlen(numstr) + strlen(denstr) + 2); if (str == NULL) { printf("ERROR (fmpz_poly_q_get_str). Memory allocation failed.\n"); abort(); } for (i = 0; i < strlen(numstr); i++) str[i] = numstr[i]; str[i++] = '/'; for (j = 0; j < strlen(denstr); j++) str[i++] = denstr[j]; str[i] = '\0'; flint_free(numstr); flint_free(denstr); return str; }
dgsl_rot_mp_t *dgsl_rot_mp_init(const long n, const fmpz_poly_t B, mpfr_t sigma, fmpq_poly_t c, const dgsl_alg_t algorithm, const oz_flag_t flags) { assert(mpfr_cmp_ui(sigma, 0) > 0); dgsl_rot_mp_t *self = (dgsl_rot_mp_t*)calloc(1, sizeof(dgsl_rot_mp_t)); if(!self) dgs_die("out of memory"); dgsl_alg_t alg = algorithm; self->n = n; self->prec = mpfr_get_prec(sigma); fmpz_poly_init(self->B); fmpz_poly_set(self->B, B); if(fmpz_poly_length(self->B) > n) dgs_die("polynomial is longer than length n"); else fmpz_poly_realloc(self->B, n); fmpz_poly_init(self->c_z); fmpq_poly_init(self->c); mpfr_init2(self->sigma, self->prec); mpfr_set(self->sigma, sigma, MPFR_RNDN); if (alg == DGSL_DETECT) { if (fmpz_poly_is_one(self->B) && (c && fmpq_poly_is_zero(c))) { alg = DGSL_IDENTITY; } else if (c && fmpq_poly_is_zero(c)) alg = DGSL_INLATTICE; else alg = DGSL_COSET; //TODO: we could test for lattice membership here } size_t tau = 3; if (2*ceil(sqrt(log2((double)n))) > tau) tau = 2*ceil(sqrt(log2((double)n))); switch(alg) { case DGSL_IDENTITY: { self->D = (dgs_disc_gauss_mp_t**)calloc(1, sizeof(dgs_disc_gauss_mp_t*)); mpfr_t c_; mpfr_init2(c_, self->prec); mpfr_set_d(c_, 0.0, MPFR_RNDN); self->D[0] = dgs_disc_gauss_mp_init(self->sigma, c_, tau, DGS_DISC_GAUSS_DEFAULT); self->call = dgsl_rot_mp_call_identity; mpfr_clear(c_); break; } case DGSL_GPV_INLATTICE: { self->D = (dgs_disc_gauss_mp_t**)calloc(n, sizeof(dgs_disc_gauss_mp_t*)); if (c && !fmpq_poly_is_zero(c)) { fmpq_t c_i; fmpq_init(c_i); for(int i=0; i<n; i++) { fmpq_poly_get_coeff_fmpq(c_i, c, i); fmpz_poly_set_coeff_fmpz(self->c_z, i, fmpq_numref(c_i)); } fmpq_clear(c_i); } mpfr_mat_t G; mpfr_mat_init(G, n, n, self->prec); mpfr_mat_set_fmpz_poly(G, B); mpfr_mat_gso(G, MPFR_RNDN); mpfr_t sigma_; mpfr_init2(sigma_, self->prec); mpfr_t norm; mpfr_init2(norm, self->prec); mpfr_t c_; mpfr_init2(c_, self->prec); mpfr_set_d(c_, 0.0, MPFR_RNDN); for(long i=0; i<n; i++) { _mpfr_vec_2norm(norm, G->rows[i], n, MPFR_RNDN); assert(mpfr_cmp_d(norm, 0.0) > 0); mpfr_div(sigma_, self->sigma, norm, MPFR_RNDN); assert(mpfr_cmp_d(sigma_, 0.0) > 0); self->D[i] = dgs_disc_gauss_mp_init(sigma_, c_, tau, DGS_DISC_GAUSS_DEFAULT); } mpfr_clear(sigma_); mpfr_clear(norm); mpfr_clear(c_); mpfr_mat_clear(G); self->call = dgsl_rot_mp_call_gpv_inlattice; break; } case DGSL_INLATTICE: { fmpq_poly_init(self->sigma_sqrt); long r= 2*ceil(sqrt(log(n))); fmpq_poly_t Bq; fmpq_poly_init(Bq); fmpq_poly_set_fmpz_poly(Bq, self->B); fmpq_poly_oz_invert_approx(self->B_inv, Bq, n, self->prec, flags); fmpq_poly_clear(Bq); _dgsl_rot_mp_sqrt_sigma_2(self->sigma_sqrt, self->B, sigma, r, n, self->prec, flags); mpfr_init2(self->r_f, self->prec); mpfr_set_ui(self->r_f, r, MPFR_RNDN); self->call = dgsl_rot_mp_call_inlattice; break; } case DGSL_COSET: dgs_die("not implemented"); default: dgs_die("not implemented"); } return self; }
void fmpz_poly_q_mul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2) { if (fmpz_poly_q_is_zero(op1) || fmpz_poly_q_is_zero(op2)) { fmpz_poly_q_zero(rop); return; } if (op1 == op2) { fmpz_poly_pow(rop->num, op1->num, 2); fmpz_poly_pow(rop->den, op1->den, 2); return; } if (rop == op1 || rop == op2) { fmpz_poly_q_t t; fmpz_poly_q_init(t); fmpz_poly_q_mul(t, op1, op2); fmpz_poly_q_swap(rop, t); fmpz_poly_q_clear(t); return; } /* From here on, we may assume that rop, op1 and op2 refer to distinct objects in memory, and that op1 and op2 are non-zero */ /* Polynomials? */ if (fmpz_poly_length(op1->den) == 1 && fmpz_poly_length(op2->den) == 1) { const slong len1 = fmpz_poly_length(op1->num); const slong len2 = fmpz_poly_length(op2->num); fmpz_poly_fit_length(rop->num, len1 + len2 - 1); if (len1 >= len2) { _fmpq_poly_mul(rop->num->coeffs, rop->den->coeffs, op1->num->coeffs, op1->den->coeffs, len1, op2->num->coeffs, op2->den->coeffs, len2); } else { _fmpq_poly_mul(rop->num->coeffs, rop->den->coeffs, op2->num->coeffs, op2->den->coeffs, len2, op1->num->coeffs, op1->den->coeffs, len1); } _fmpz_poly_set_length(rop->num, len1 + len2 - 1); _fmpz_poly_set_length(rop->den, 1); return; } fmpz_poly_gcd(rop->num, op1->num, op2->den); if (fmpz_poly_is_one(rop->num)) { fmpz_poly_gcd(rop->den, op2->num, op1->den); if (fmpz_poly_is_one(rop->den)) { fmpz_poly_mul(rop->num, op1->num, op2->num); fmpz_poly_mul(rop->den, op1->den, op2->den); } else { fmpz_poly_div(rop->num, op2->num, rop->den); fmpz_poly_mul(rop->num, op1->num, rop->num); fmpz_poly_div(rop->den, op1->den, rop->den); fmpz_poly_mul(rop->den, rop->den, op2->den); } } else { fmpz_poly_gcd(rop->den, op2->num, op1->den); if (fmpz_poly_is_one(rop->den)) { fmpz_poly_div(rop->den, op2->den, rop->num); fmpz_poly_mul(rop->den, op1->den, rop->den); fmpz_poly_div(rop->num, op1->num, rop->num); fmpz_poly_mul(rop->num, rop->num, op2->num); } else { fmpz_poly_t t, u; fmpz_poly_init(t); fmpz_poly_init(u); fmpz_poly_div(t, op1->num, rop->num); fmpz_poly_div(u, op2->den, rop->num); fmpz_poly_div(rop->num, op2->num, rop->den); fmpz_poly_mul(rop->num, t, rop->num); fmpz_poly_div(rop->den, op1->den, rop->den); fmpz_poly_mul(rop->den, rop->den, u); fmpz_poly_clear(t); fmpz_poly_clear(u); } } }
int main(void) { flint_rand_t state; long i; printf("inv...."); fflush(stdout); flint_randinit(state); /* Test aliasing */ for (i = 0; i < 400; i++) { fmpz_poly_mat_t A, Ainv; fmpz_poly_t den1, den2; long n, bits, deg; float density; int ns1, ns2; int result; n = n_randint(state, 8); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(Ainv, n, n); fmpz_poly_init(den1); fmpz_poly_init(den2); fmpz_poly_mat_randtest_sparse(A, state, deg, bits, density); ns1 = fmpz_poly_mat_inv(Ainv, den1, A); ns2 = fmpz_poly_mat_inv(A, den2, A); result = ns1 == ns2; if (result && ns1 != 0) { result = fmpz_poly_equal(den1, den2) && fmpz_poly_mat_equal(A, Ainv); } if (!result) { printf("FAIL (aliasing)!\n"); fmpz_poly_mat_print(A, "x"); printf("\n"); fmpz_poly_mat_print(Ainv, "x"); printf("\n"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(Ainv); fmpz_poly_clear(den1); fmpz_poly_clear(den2); } /* Check A^(-1) = A = 1 */ for (i = 0; i < 1000; i++) { fmpz_poly_mat_t A, Ainv, B, Iden; fmpz_poly_t den, det; long n, bits, deg; float density; int nonsingular; n = n_randint(state, 10); deg = 1 + n_randint(state, 5); bits = 1 + n_randint(state, 100); density = n_randint(state, 100) * 0.01; fmpz_poly_mat_init(A, n, n); fmpz_poly_mat_init(Ainv, n, n); fmpz_poly_mat_init(B, n, n); fmpz_poly_mat_init(Iden, n, n); fmpz_poly_init(den); fmpz_poly_init(det); fmpz_poly_mat_randtest_sparse(A, state, deg, bits, density); nonsingular = fmpz_poly_mat_inv(Ainv, den, A); fmpz_poly_mat_det_interpolate(det, A); if (n == 0) { if (nonsingular == 0 || !fmpz_poly_is_one(den)) { printf("FAIL: expected empty matrix to pass\n"); abort(); } } else { if (!fmpz_poly_equal(den, det)) { fmpz_poly_neg(det, det); printf("FAIL: den != det(A)\n"); abort(); } fmpz_poly_mat_mul(B, Ainv, A); fmpz_poly_mat_one(Iden); fmpz_poly_mat_scalar_mul_fmpz_poly(Iden, Iden, den); if (!fmpz_poly_mat_equal(B, Iden)) { printf("FAIL:\n"); printf("A:\n"); fmpz_poly_mat_print(A, "x"); printf("Ainv:\n"); fmpz_poly_mat_print(Ainv, "x"); printf("B:\n"); fmpz_poly_mat_print(B, "x"); printf("den:\n"); fmpz_poly_print_pretty(den, "x"); abort(); } } fmpz_poly_clear(den); fmpz_poly_clear(det); fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(Ainv); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(Iden); } flint_randclear(state); _fmpz_cleanup(); printf("PASS\n"); return 0; }
bool poly_inverse_poly_p(fmpz_poly_t Fp, const fmpz_poly_t a, const ntru_params *params) { bool retval = false; int k = 0, j = 0; fmpz *b_last; fmpz_poly_t a_tmp, b, c, f, g; /* general initialization of temp variables */ fmpz_poly_init(b); fmpz_poly_set_coeff_ui(b, 0, 1); fmpz_poly_init(c); fmpz_poly_init(f); fmpz_poly_set(f, a); /* set g(x) = x^N − 1 */ fmpz_poly_init(g); fmpz_poly_set_coeff_si(g, 0, -1); fmpz_poly_set_coeff_si(g, params->N, 1); /* avoid side effects */ fmpz_poly_init(a_tmp); fmpz_poly_set(a_tmp, a); fmpz_poly_zero(Fp); while (1) { while (fmpz_poly_get_coeff_ptr(f, 0) && fmpz_is_zero(fmpz_poly_get_coeff_ptr(f, 0))) { for (uint32_t i = 1; i <= params->N; i++) { fmpz *f_coeff = fmpz_poly_get_coeff_ptr(f, i); fmpz *c_coeff = fmpz_poly_get_coeff_ptr(c, params->N - i); /* f(x) = f(x) / x */ fmpz_poly_set_coeff_fmpz_n(f, i - 1, f_coeff); /* c(x) = c(x) * x */ fmpz_poly_set_coeff_fmpz_n(c, params->N + 1 - i, c_coeff); } fmpz_poly_set_coeff_si(f, params->N, 0); fmpz_poly_set_coeff_si(c, 0, 0); k++; if (fmpz_poly_degree(f) == -1) goto cleanup; } if (fmpz_poly_is_zero(g) == 1) goto cleanup; if (fmpz_poly_degree(f) == 0) break; if (fmpz_poly_degree(f) < fmpz_poly_degree(g)) { /* exchange f and g and exchange b and c */ fmpz_poly_swap(f, g); fmpz_poly_swap(b, c); } { fmpz_poly_t c_tmp, g_tmp; fmpz_t u, mp_tmp; fmpz_init(u); fmpz_zero(u); fmpz_init_set(mp_tmp, fmpz_poly_get_coeff_ptr(f, 0)); fmpz_poly_init(g_tmp); fmpz_poly_set(g_tmp, g); fmpz_poly_init(c_tmp); fmpz_poly_set(c_tmp, c); /* u = f[0] * g[0]^(-1) mod p */ /* = (f[0] mod p) * (g[0] inverse mod p) mod p */ fmpz_invmod_ui(u, fmpz_poly_get_coeff_ptr(g, 0), params->p); fmpz_mod_ui(mp_tmp, mp_tmp, params->p); fmpz_mul(u, mp_tmp, u); fmpz_mod_ui(u, u, params->p); /* f = f - u * g mod p */ fmpz_poly_scalar_mul_fmpz(g_tmp, g_tmp, u); fmpz_poly_sub(f, f, g_tmp); fmpz_poly_mod_unsigned(f, params->p); /* b = b - u * c mod p */ fmpz_poly_scalar_mul_fmpz(c_tmp, c_tmp, u); fmpz_poly_sub(b, b, c_tmp); fmpz_poly_mod_unsigned(b, params->p); fmpz_clear(u); fmpz_poly_clear(g_tmp); fmpz_poly_clear(c_tmp); } } k = k % params->N; b_last = fmpz_poly_get_coeff_ptr(b, params->N); if (fmpz_cmp_si_n(b_last, 0)) goto cleanup; /* Fp(x) = x^(N-k) * b(x) */ for (int i = params->N - 1; i >= 0; i--) { fmpz *b_i; /* b(X) = f[0]^(-1) * b(X) (mod p) */ { fmpz_t mp_tmp; fmpz_init(mp_tmp); fmpz_invmod_ui(mp_tmp, fmpz_poly_get_coeff_ptr(f, 0), params->p); if (fmpz_poly_get_coeff_ptr(b, i)) { fmpz_mul(fmpz_poly_get_coeff_ptr(b, i), fmpz_poly_get_coeff_ptr(b, i), mp_tmp); fmpz_mod_ui(fmpz_poly_get_coeff_ptr(b, i), fmpz_poly_get_coeff_ptr(b, i), params->p); } } j = i - k; if (j < 0) j = j + params->N; b_i = fmpz_poly_get_coeff_ptr(b, i); fmpz_poly_set_coeff_fmpz_n(Fp, j, b_i); } /* check if the f * Fp = 1 (mod p) condition holds true */ fmpz_poly_set(a_tmp, a); poly_starmultiply(a_tmp, a_tmp, Fp, params, params->p); if (fmpz_poly_is_one(a_tmp)) retval = true; else fmpz_poly_zero(Fp); cleanup: fmpz_poly_clear(a_tmp); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(f); fmpz_poly_clear(g); return retval; }
bool poly_inverse_poly_q(fmpz_poly_t Fq, const fmpz_poly_t a, const ntru_params *params) { bool retval = false; int k = 0, j = 0; fmpz *b_last; fmpz_poly_t a_tmp, b, c, f, g; /* general initialization of temp variables */ fmpz_poly_init(b); fmpz_poly_set_coeff_ui(b, 0, 1); fmpz_poly_init(c); fmpz_poly_init(f); fmpz_poly_set(f, a); /* set g(x) = x^N − 1 */ fmpz_poly_init(g); fmpz_poly_set_coeff_si(g, 0, -1); fmpz_poly_set_coeff_si(g, params->N, 1); /* avoid side effects */ fmpz_poly_init(a_tmp); fmpz_poly_set(a_tmp, a); fmpz_poly_zero(Fq); while (1) { while (fmpz_poly_get_coeff_ptr(f, 0) && fmpz_is_zero(fmpz_poly_get_coeff_ptr(f, 0))) { for (uint32_t i = 1; i <= params->N; i++) { fmpz *f_coeff = fmpz_poly_get_coeff_ptr(f, i); fmpz *c_coeff = fmpz_poly_get_coeff_ptr(c, params->N - i); /* f(x) = f(x) / x */ fmpz_poly_set_coeff_fmpz_n(f, i - 1, f_coeff); /* c(x) = c(x) * x */ fmpz_poly_set_coeff_fmpz_n(c, params->N + 1 - i, c_coeff); } fmpz_poly_set_coeff_si(f, params->N, 0); fmpz_poly_set_coeff_si(c, 0, 0); k++; if (fmpz_poly_degree(f) == -1) goto cleanup; } if (fmpz_poly_is_zero(g) == 1) goto cleanup; if (fmpz_poly_degree(f) == 0) break; if (fmpz_poly_degree(f) < fmpz_poly_degree(g)) { fmpz_poly_swap(f, g); fmpz_poly_swap(b, c); } fmpz_poly_add(f, g, f); fmpz_poly_mod_unsigned(f, 2); fmpz_poly_add(b, c, b); fmpz_poly_mod_unsigned(b, 2); } k = k % params->N; b_last = fmpz_poly_get_coeff_ptr(b, params->N); if (fmpz_cmp_si_n(b_last, 0)) goto cleanup; /* Fq(x) = x^(N-k) * b(x) */ for (int i = params->N - 1; i >= 0; i--) { fmpz *b_i; j = i - k; if (j < 0) j = j + params->N; b_i = fmpz_poly_get_coeff_ptr(b, i); fmpz_poly_set_coeff_fmpz_n(Fq, j, b_i); } poly_mod2_to_modq(Fq, a_tmp, params); /* check if the f * Fq = 1 (mod p) condition holds true */ fmpz_poly_set(a_tmp, a); poly_starmultiply(a_tmp, a_tmp, Fq, params, params->q); if (fmpz_poly_is_one(a_tmp)) retval = true; else fmpz_poly_zero(Fq); cleanup: fmpz_poly_clear(a_tmp); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(f); fmpz_poly_clear(g); return retval; }