int fmpcb_poly_contains_fmpq_poly(const fmpcb_poly_t poly1, const fmpq_poly_t poly2) { long i; fmpq_t t; if (poly2->length > poly1->length) return 0; fmpq_init(t); for (i = 0; i < poly2->length; i++) { fmpq_poly_get_coeff_fmpq(t, poly2, i); if (!fmpcb_contains_fmpq(poly1->coeffs + i, t)) { fmpq_clear(t); return 0; } } fmpq_clear(t); for (i = poly2->length; i < poly1->length; i++) if (!fmpcb_contains_zero(poly1->coeffs + i)) return 0; return 1; }
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; }
int fmpq_poly_oz_sqrt_approx_pade(fmpq_poly_t f_sqrt, const fmpq_poly_t f, const long n, const int p, const mpfr_prec_t prec, const mpfr_prec_t bound, oz_flag_t flags, const fmpq_poly_t init) { fmpq_poly_t y; fmpq_poly_init(y); fmpq_poly_t y_next; fmpq_poly_init(y_next); fmpq_poly_t z; fmpq_poly_init(z); fmpq_poly_t z_next; fmpq_poly_init(z_next); mpfr_t norm; mpfr_init2(norm, prec); mpfr_t prev_norm; mpfr_init2(prev_norm, prec); mpfr_t log_f; mpfr_init2(log_f, prec); if (init) { // z = y/x fmpq_poly_set(y, init); _fmpq_poly_oz_invert_approx(z, f, n, prec); fmpq_poly_oz_mul(z, z, y, n); } else { fmpq_poly_set(y, f); fmpq_poly_set_coeff_si(z, 0, 1); } fmpq_t *xi = (fmpq_t*)calloc(p, sizeof(fmpq_t)); fmpq_t *a2 = (fmpq_t*)calloc(p, sizeof(fmpq_t)); fmpq_t *c = (fmpq_t*)calloc(p, sizeof(fmpq_t)); fmpq_poly_t *t_ = (fmpq_poly_t*)calloc(p, sizeof(fmpq_poly_t)); fmpq_poly_t *s_ = (fmpq_poly_t*)calloc(p, sizeof(fmpq_poly_t)); mpfr_t pi; mpfr_init2(pi, 4*prec); mpfr_const_pi(pi, MPFR_RNDN); #pragma omp parallel for for(int i=0; i<p; i++) { mpfr_t xi_r; mpfr_init2(xi_r, 4*prec); mpfr_t a2_r; mpfr_init2(a2_r, 4*prec); /* ζ_i = 1/2 * (1 + cos( (2·i -1)·π/(2·p) )) */ mpfr_set_si(xi_r, 2*i+1, MPFR_RNDN); mpfr_mul(xi_r, xi_r, pi, MPFR_RNDN); mpfr_div_si(xi_r, xi_r, 2*p, MPFR_RNDN); mpfr_cos(xi_r, xi_r, MPFR_RNDN); mpfr_add_si(xi_r, xi_r, 1, MPFR_RNDN); mpfr_div_si(xi_r, xi_r, 2, MPFR_RNDN); /* α_i^2 = 1/ζ_i -1 */ mpfr_set_si(a2_r, 1, MPFR_RNDN); mpfr_div(a2_r, a2_r, xi_r, MPFR_RNDN); mpfr_sub_si(a2_r, a2_r, 1, MPFR_RNDN); fmpq_init(xi[i]); fmpq_init(a2[i]); fmpq_set_mpfr(xi[i], xi_r, MPFR_RNDN); fmpq_set_mpfr(a2[i], a2_r, MPFR_RNDN); fmpq_init(c[i]); fmpq_poly_init(t_[i]); fmpq_poly_init(s_[i]); mpfr_clear(xi_r); mpfr_clear(a2_r); } mpfr_clear(pi); uint64_t t = oz_walltime(0); int r = 0; int cont = 1; for(long k=0; cont; k++) { if (k == 0 || mpfr_cmp_ui(prev_norm, 1) > 0) _fmpq_poly_oz_sqrt_approx_scale(y, z, n, prec); /* T = sum([1/xi[i] * ~(Z*Y + a2[i]) for i in range(p)]) */ #pragma omp parallel for for(int i=0; i<p; i++) { fmpq_poly_oz_mul(t_[i], z, y, n); fmpq_poly_get_coeff_fmpq(c[i], t_[i], 0); fmpq_add(c[i], c[i], a2[i]); fmpq_poly_set_coeff_fmpq(t_[i], 0, c[i]); fmpq_poly_scalar_mul_fmpq(t_[i], t_[i], xi[i]); _fmpq_poly_oz_invert_approx(s_[i], t_[i], n, prec); } for(int i=1; i<p; i++) fmpq_poly_add(s_[0], s_[0], s_[i]); #pragma omp parallel sections { #pragma omp section { fmpq_poly_oz_mul(y_next, y, s_[0], n); fmpq_poly_scalar_div_si(y_next, y_next, p); fmpq_poly_set(y, y_next); } #pragma omp section { fmpq_poly_oz_mul(z_next, z, s_[0], n); fmpq_poly_scalar_div_si(z_next, z_next, p); fmpq_poly_set(z, z_next); } } cont = !_fmpq_poly_oz_sqrt_approx_break(norm, y, f, n, bound, prec); if(flags & OZ_VERBOSE) { mpfr_log2(log_f, norm, MPFR_RNDN); mpfr_fprintf(stderr, "Computing sqrt(Σ):: k: %4d, Δ=|sqrt(Σ)^2-Σ|: %7.2Rf", k, log_f); fprintf(stderr, " <? %4ld, ", -bound); fprintf(stderr, "t: %8.2fs\n", oz_seconds(oz_walltime(t))); fflush(0); } if (cont) { if (k>0 && mpfr_cmp_ui_2exp(norm, 1, bound) >= 0) { /* something went really wrong */ r = -1; break; } if (k>0 && mpfr_cmp(norm, prev_norm) >= 0) { /* we don't converge any more */ r = 1; break; } mpfr_set(prev_norm, norm, MPFR_RNDN); } } for(int i=0; i<p; i++) { fmpq_clear(xi[i]); fmpq_clear(a2[i]); fmpq_clear(c[i]); fmpq_poly_clear(t_[i]); fmpq_poly_clear(s_[i]); } free(xi); free(a2); free(c); free(t_); free(s_); mpfr_clear(log_f); fmpq_poly_set(f_sqrt, y); mpfr_clear(norm); mpfr_clear(prev_norm); fmpq_poly_clear(y_next); fmpq_poly_clear(y); fmpq_poly_clear(z_next); fmpq_poly_clear(z); return r; }