int main(int argc, char *argv[]) { assert(argc>=3); const long n = atol(argv[1]); const long prec = atol(argv[2]); flint_rand_t randstate; flint_randinit_seed(randstate, 0x1337, 1); mpfr_t sigma; mpfr_init2(sigma, prec); mpfr_set_d(sigma, _gghlite_sigma(n), MPFR_RNDN); fmpz_poly_t g; fmpz_poly_init(g); fmpz_poly_sample_sigma(g, n, sigma, randstate); fmpq_poly_t gq; fmpq_poly_init(gq); fmpq_poly_set_fmpz_poly(gq, g); fmpq_poly_t g_inv; fmpq_poly_init(g_inv); fmpq_poly_t modulus; fmpq_poly_init_oz_modulus(modulus, n); printf(" n: %4ld, log σ': %7.2f, ",n, log2(_gghlite_sigma(n))); uint64_t t = ggh_walltime(0); fmpq_poly_invert_mod(g_inv, gq, modulus); t = ggh_walltime(t); printf("xgcd: %7.3f, ", t/1000000.0); fflush(0); t = ggh_walltime(0); _fmpq_poly_oz_invert_approx(g_inv, gq, n, 160); t = ggh_walltime(t); printf("%4ld: %7.3f, ", prec, t/1000000.0); fflush(0); t = ggh_walltime(0); fmpq_poly_oz_invert_approx(g_inv, gq, n, 160, 0); t = ggh_walltime(t); printf("%4lditer: %7.3f, ", prec, t/1000000.0); fflush(0); t = ggh_walltime(0); _fmpq_poly_oz_invert_approx(g_inv, gq, n, 0); t = ggh_walltime(t); printf("∞: %7.3f.", t/1000000.0); printf("\n"); mpfr_clear(sigma); fmpz_poly_clear(g); fmpq_poly_clear(gq); fmpq_poly_clear(g_inv); fmpq_poly_clear(modulus); flint_randclear(randstate); flint_cleanup(); return 0; }
void renf_randtest(renf_t nf, flint_rand_t state, slong len, slong prec, mp_bitcnt_t bits) { fmpz_poly_t p; fmpq_poly_t p2; fmpz * c_array; slong * k_array; slong n_interval, n_exact; ulong i; arb_t emb; /* compute a random irreducible polynomial */ if (len <= 1) { fprintf(stderr, "ERROR (renf_randtest): got length < 2\n"); abort(); } fmpz_poly_init(p); do{ fmpz_poly_randtest_irreducible(p, state, len, bits); }while(!fmpz_poly_has_real_root(p)); /* pick a random real root */ c_array = _fmpz_vec_init(p->length); k_array = malloc((p->length) * sizeof(slong)); n_interval = 0; fmpz_poly_isolate_real_roots(NULL, &n_exact, c_array, k_array, &n_interval, p); if (n_interval == 0) { fprintf(stderr, "Runtime error\n"); abort(); } i = n_randint(state, n_interval); /* construct the associated number field */ arb_init(emb); arb_from_interval(emb, c_array+i, k_array[i], fmpz_bits(c_array + i) + FLINT_MAX(k_array[i], 0) + 2); fmpq_poly_init(p2); fmpq_poly_set_fmpz_poly(p2, p); /* NOTE: renf init might not be happy with the ball emb */ renf_init(nf, p2, emb, prec); _fmpz_vec_clear(c_array, p->length); free(k_array); fmpz_poly_clear(p); fmpq_poly_clear(p2); arb_clear(emb); }
int dgsl_rot_mp_call_plus_fmpz_poly(fmpz_poly_t rop, const dgsl_rot_mp_t *self, const fmpz_poly_t c, gmp_randstate_t state) { fmpz_poly_t t; fmpz_poly_init(t); fmpz_poly_set(t, c); fmpq_poly_t tq; fmpq_poly_init(tq); // == 0 fmpq_poly_set_fmpz_poly(tq, t); fmpq_poly_neg(tq, tq); dgsl_rot_mp_call_recenter_fmpq_poly(rop, self, tq, state); fmpz_poly_add(rop, rop, t); fmpq_poly_clear(tq); fmpz_poly_clear(t); return 0; }
void _dgsl_rot_mp_sqrt_sigma_2(fmpq_poly_t rop, const fmpz_poly_t g, const mpfr_t sigma, const int r, const long n, const mpfr_prec_t prec, const oz_flag_t flags) { fmpq_poly_zero(rop); fmpq_t r_q2; fmpq_init(r_q2); fmpq_set_si(r_q2, r, 1); fmpq_mul(r_q2, r_q2, r_q2); fmpq_neg(r_q2, r_q2); fmpq_poly_set_coeff_fmpq(rop, 0, r_q2); fmpq_clear(r_q2); fmpq_poly_t g_q; fmpq_poly_init(g_q); fmpq_poly_set_fmpz_poly(g_q, g); fmpq_poly_t ng; fmpq_poly_init(ng); fmpq_poly_oz_invert_approx(ng, g_q, n, prec, flags); fmpq_poly_t ngt; fmpq_poly_init(ngt); fmpq_poly_oz_conjugate(ngt, ng, n); fmpq_poly_t nggt; fmpq_poly_init(nggt); fmpq_poly_oz_mul(nggt, ng, ngt, n); /** We compute sqrt(g^-T · g^-1) to use it as the starting point for convergence on sqrt(σ^2 · g^-T · g^-1 - r^2) below. We can compute the former with less precision than the latter */ mpfr_t norm; mpfr_init2(norm, prec); fmpz_poly_eucl_norm_mpfr(norm, g, MPFR_RNDN); double p = mpfr_get_d(norm, MPFR_RNDN); /** |g^-1| ~= 1/|g| |g^-T| ~= |g^-1| |g^-1·g^-T| ~= sqrt(n)·|g^-T|·|g^-1| */ fmpq_poly_t sqrt_start; fmpq_poly_init(sqrt_start); p = log2(n) + 4*log2(p); int fail = -1; while (fail) { p = 2*p; if (fail<0) fail = fmpq_poly_oz_sqrt_approx_db(sqrt_start, nggt, n, p, prec/2, flags, NULL); else fail = fmpq_poly_oz_sqrt_approx_db(sqrt_start, nggt, n, p, prec/2, flags, sqrt_start); if(fail) fprintf(stderr, "FAILED for precision %7.1f with code (%d), doubling precision.\n", p, fail); } fmpq_t sigma2; fmpq_init(sigma2); fmpq_set_mpfr(sigma2, sigma, MPFR_RNDN); fmpq_poly_scalar_mul_fmpq(sqrt_start, sqrt_start, sigma2); fmpq_mul(sigma2, sigma2, sigma2); fmpq_poly_scalar_mul_fmpq(nggt, nggt, sigma2); fmpq_clear(sigma2); fmpq_poly_add(rop, rop, nggt); p = p + 2*log2(mpfr_get_d(sigma, MPFR_RNDN)); fmpq_poly_oz_sqrt_approx_babylonian(rop, rop, n, p, prec, flags, sqrt_start); mpfr_clear(norm); fmpq_poly_clear(g_q); fmpq_poly_clear(ng); fmpq_poly_clear(ngt); fmpq_poly_clear(nggt); fmpq_poly_clear(sqrt_start); }
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; }