void dgsl_mp_clear(dgsl_mp_t *self) { if (!self) return; _fmpz_vec_clear(self->c_z, fmpz_mat_ncols(self->B)); _mpfr_vec_clear(self->c, fmpz_mat_ncols(self->B)); if (!fmpz_mat_is_empty(self->B)) { fmpz_mat_clear(self->B); } if (!mpfr_mat_is_empty(self->G)) { mpfr_mat_clear(self->G); } if(self->call == dgsl_mp_call_identity) { if(self->D) { dgs_disc_gauss_mp_clear(self->D[0]); free(self->D); } } mpfr_clear(self->sigma); free(self); }
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 test_F_mpz_LLL_randsimdioph() { mpz_mat_t m_mat; F_mpz_mat_t F_mat; int result = 1; ulong bits1, bits2; F_mpz_t fzero; F_mpz_init(fzero); ulong count1; for (count1 = 0; (count1 < 10*ITER) && (result == 1) ; count1++) { #if TRACE printf("count1 == %ld\n", count1); #endif ulong r = z_randint(200) + 1; ulong c = r; F_mpz_mat_init(F_mat, r, c); mpz_mat_init(m_mat, r, c); bits1 = z_randint(200) + 1; bits2 = z_randint(5) + 1; mpz_mat_randsimdioph(m_mat, r, c, bits1, bits2); mpz_mat_to_F_mpz_mat(F_mat, m_mat); F_mpz_set_d_2exp(fzero, 2.0, bits2); // good stuff here U_LLL_with_removal(F_mat, 350, fzero); mp_prec_t prec; prec = 20; __mpfr_struct ** Q, ** R; Q = mpfr_mat_init2(r, c, prec); R = mpfr_mat_init2(r, r, prec); F_mpz_mat_RQ_factor(F_mat, R, Q, r, c, prec); // should be that RQ = FM_copy /* long j; if (count1 == 29){ mpfr_printf("%.12Rf was R[i][i] for i = %ld\n", R[0] + 0, 0); for (j = 1; j < r; j++) { mpfr_printf("%.12Rf was R[i][i+1] for i = %ld\n", R[j] + j - 1, j); mpfr_printf("%.12Rf was R[i+1][i+1] for i = %ld\n", R[j] + j, j); } } */ result = mpfr_mat_R_reduced(R, r, (double) DELTA, (double) ETA, prec); mpfr_mat_clear(Q, r, c); mpfr_mat_clear(R, r, r); //result here result = mpz_mat_equal(res1, res2); if (!result) { F_mpz_mat_print_pretty(F_mat); printf("Error: bits1 = %ld, count1 = %ld\n", bits1, count1); } F_mpz_mat_clear(F_mat); mpz_mat_clear(m_mat); } F_mpz_clear(fzero); return result; }
dgsl_mp_t *dgsl_mp_init(const fmpz_mat_t B, mpfr_t sigma, mpfr_t *c, const dgsl_alg_t algorithm) { assert(mpfr_cmp_ui(sigma, 0) > 0); dgsl_mp_t *self = (dgsl_mp_t*)calloc(1, sizeof(dgsl_mp_t)); if(!self) dgs_die("out of memory"); dgsl_alg_t alg = algorithm; long m = fmpz_mat_nrows(B); long n = fmpz_mat_ncols(B); const mpfr_prec_t prec = mpfr_get_prec(sigma); fmpz_mat_init_set(self->B, B); self->c_z = _fmpz_vec_init(n); self->c = _mpfr_vec_init(n, prec); mpfr_init2(self->sigma, prec); mpfr_set(self->sigma, sigma, MPFR_RNDN); if (alg == DGSL_DETECT) { if (fmpz_mat_is_one(self->B)) { alg = DGSL_IDENTITY; } else if (_mpfr_vec_is_zero(c, n)) alg = DGSL_INLATTICE; else alg = DGSL_COSET; //TODO: we could test for lattice membership here } mpfr_t c_; mpfr_init2(c_, prec); 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_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_mp_call_identity; break; case DGSL_INLATTICE: self->D = (dgs_disc_gauss_mp_t**)calloc(m, sizeof(dgs_disc_gauss_mp_t*)); if (c) _fmpz_vec_set_mpfr_vec(self->c_z, c, n); mpfr_mat_t G; mpfr_mat_init(G, m, n, prec); mpfr_mat_set_fmpz_mat(G, B); mpfr_mat_gso(G, MPFR_RNDN); mpfr_t sigma_; mpfr_init2(sigma_, prec); mpfr_t norm; mpfr_init2(norm, prec); mpfr_set_d(c_, 0.0, MPFR_RNDN); for(long i=0; i<m; 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_mat_clear(G); self->call = dgsl_mp_call_inlattice; break; case DGSL_COSET: mpfr_mat_init(self->G, m, n, prec); mpfr_mat_set_fmpz_mat(self->G, B); mpfr_mat_gso(self->G, MPFR_RNDN); self->call = dgsl_mp_call_coset; break; default: dgs_die("not implemented"); } mpfr_clear(c_); return self; }
int test_F_mpz_LLL_randajtai() { mpz_mat_t m_mat; F_mpz_mat_t F_mat; int result = 1; ulong bits; F_mpz_t fzero; F_mpz_init(fzero); ulong count1; for (count1 = 0; (count1 < 100*ITER) && (result == 1) ; count1++) { #if TRACE printf("count1 == %ld\n", count1); #endif ulong r = z_randint(10)+1; ulong c = r; F_mpz_mat_init(F_mat, r, c); mpz_mat_init(m_mat, r, c); bits = z_randint(200) + 1; mpz_mat_randajtai(m_mat, r, c, .5); mpz_mat_to_F_mpz_mat(F_mat, m_mat); F_mpz_set_d_2exp(fzero, (double) 2*r, 1); // good stuff here //F_mpz_mat_print_pretty(F_mat); long newd = U_LLL_with_removal(F_mat, 350, fzero); mp_prec_t prec; prec = 50; __mpfr_struct ** Q, ** R; Q = mpfr_mat_init2(r, c, prec); R = mpfr_mat_init2(r, r, prec); F_mpz_mat_RQ_factor(F_mat, R, Q, r, c, prec); // should be that RQ = FM_copy long j; #if TRACE if (count1 == 30){ mpfr_printf("%.12Rf was R[i][i] for i = %ld\n", R[0] + 0, 0); for (j = 1; j < r; j++) { mpfr_printf("%.12Rf was R[i][i+1] for i = %ld\n", R[j] + j - 1, j); mpfr_printf("%.12Rf was R[i+1][i+1] for i = %ld\n", R[j] + j, j); } } #endif result = mpfr_mat_R_reduced(R, r, (double) DELTA-.01, (double) ETA+.01, prec); mpfr_mat_clear(Q, r, c); mpfr_mat_clear(R, r, r); //result here result = mpz_mat_equal(res1, res2); if (!result) { printf("Error: bits = %ld, count1 = %ld, newd = %ld\n", bits, count1, newd); } F_mpz_mat_clear(F_mat); mpz_mat_clear(m_mat); } F_mpz_clear(fzero); return result; }