/** @brief Test if dual SVP reduction returns reduced basis. @param A input lattice @param b shortest dual vector @return */ template <class ZT> int test_dsvp_reduce(ZZ_mat<ZT> &A, IntVect &b) { IntMatrix u; int d = A.get_rows(); Float normb; if (dual_length(normb, A, b)) { return 1; } int status = lll_reduction(A, u, LLL_DEF_DELTA, LLL_DEF_ETA, LM_WRAPPER, FT_DEFAULT, 0, LLL_DEFAULT); if (status != RED_SUCCESS) { cerr << "LLL reduction failed: " << get_red_status_str(status) << endl; return status; } IntMatrix empty_mat; MatGSO<Integer, Float> gso(A, empty_mat, empty_mat, GSO_INT_GRAM); LLLReduction<Integer, Float> lll_obj(gso, LLL_DEF_DELTA, LLL_DEF_ETA, LLL_DEFAULT); vector<Strategy> strategies; BKZParam dummy(d, strategies); BKZReduction<Float> bkz_obj(gso, lll_obj, dummy); bool clean = true; bkz_obj.svp_reduction_ex(0, d, dummy, clean, true); status = bkz_obj.status; if (status != RED_SUCCESS) { cerr << "Failure: " << get_red_status_str(status) << endl; return status; } Float norm_sol; Integer zero; zero = 0; IntVect e_n(d, zero); e_n[d - 1] = 1; if (dual_length(norm_sol, A, e_n)) { return 1; } Float error; error = 1; error.mul_2si(error, -(int)error.get_prec()); normb += error; if (norm_sol > normb) { cerr << "Last dual vector too long by more than " << error << endl; return 1; } return 0; }
/** @brief Compute the norm of a dual vector (specified by coefficients in the dual basis). @param A input lattice @param b coefficients of shortest dual vector @return */ template <class ZT> int dual_length(Float &norm, ZZ_mat<ZT> &A, const IntVect &coords) { int d = coords.size(); if (A.get_rows() != d) { cerr << "DSVP length error: Coefficient vector has wrong dimension: "; cerr << A.get_rows() << " vs " << d << endl; return 1; } FloatVect coords_d(d); for (int i = 0; i < d; i++) { coords_d[i] = coords[i].get_d(); } IntMatrix empty_mat; MatGSO<Integer, Float> gso(A, empty_mat, empty_mat, GSO_INT_GRAM); if (!gso.update_gso()) { cerr << "GSO Failure." << endl; return 1; } Float tmp; gso.get_r(tmp, d - 1, d - 1); tmp.pow_si(tmp, -1); FloatVect alpha(d); Float mu, alpha2, r_inv; norm = 0.0; for (int i = 0; i < d; i++) { alpha[i] = coords_d[i]; for (int j = 0; j < i; j++) { gso.get_mu(mu, i, j); alpha[i] -= mu * alpha[j]; } gso.get_r(r_inv, i, i); r_inv.pow_si(r_inv, -1); alpha2.pow_si(alpha[i], 2); norm += alpha2 * r_inv; } return 0; }
template <class ZT> void zeros_last(ZZ_mat<ZT> &b, ZZ_mat<ZT> &u, ZZ_mat<ZT> &u_inv_t) { int i, d = b.get_rows(); for (i = 0; i < d && b[i].is_zero(); i++) { } if (i > 0 && i < d) { b.rotate(0, i, d - 1); if (!u.empty()) u.rotate(0, i, d - 1); if (!u_inv_t.empty()) u_inv_t.rotate(0, i, d - 1); } }