/** * interface called from call_bkz() from main.cpp. */ int bkz_reduction(IntMatrix *B, IntMatrix *U, const BKZParam ¶m, FloatType float_type, int precision) { IntMatrix empty_mat; IntMatrix &u = U ? *U : empty_mat; IntMatrix &u_inv = empty_mat; FPLLL_CHECK(B, "B == NULL in bkzReduction"); if (U && (!u.empty())) { u.gen_identity(B->get_rows()); } double lll_delta = param.delta < 1 ? param.delta : LLL_DEF_DELTA; FloatType sel_ft = (float_type != FT_DEFAULT) ? float_type : FT_DOUBLE; FPLLL_CHECK(!(sel_ft == FT_MPFR && precision == 0), "Missing precision for BKZ with floating point type mpfr"); /* lllwrapper (no FloatType needed, -m ignored) */ if (param.flags & BKZ_NO_LLL) zeros_last(*B, u, u_inv); else { Wrapper wrapper(*B, u, u_inv, lll_delta, LLL_DEF_ETA, LLL_DEFAULT); if (!wrapper.lll()) return wrapper.status; } /* bkz (with float_type) */ int status; if (sel_ft == FT_DOUBLE) { status = bkz_reduction_f<FP_NR<double>>(*B, param, sel_ft, lll_delta, u, u_inv); } #ifdef FPLLL_WITH_LONG_DOUBLE else if (sel_ft == FT_LONG_DOUBLE) { status = bkz_reduction_f<FP_NR<long double>>(*B, param, sel_ft, lll_delta, u, u_inv); } #endif #ifdef FPLLL_WITH_DPE else if (sel_ft == FT_DPE) { status = bkz_reduction_f<FP_NR<dpe_t>>(*B, param, sel_ft, lll_delta, u, u_inv); } #endif #ifdef FPLLL_WITH_QD else if (sel_ft == FT_DD) { status = bkz_reduction_f<FP_NR<dd_real>>(*B, param, sel_ft, lll_delta, u, u_inv); } else if (sel_ft == FT_QD) { status = bkz_reduction_f<FP_NR<qd_real>>(*B, param, sel_ft, lll_delta, u, u_inv); } #endif else if (sel_ft == FT_MPFR) { int old_prec = FP_NR<mpfr_t>::set_prec(precision); status = bkz_reduction_f<FP_NR<mpfr_t>>(*B, param, sel_ft, lll_delta, u, u_inv); FP_NR<mpfr_t>::set_prec(old_prec); } else { FPLLL_ABORT("Compiled without support for BKZ reduction with " << FLOAT_TYPE_STR[sel_ft]); } zeros_first(*B, u, u_inv); return status; }
static int shortest_vector_ex(IntMatrix &b, IntVect &sol_coord, SVPMethod method, const vector<double> &pruning, int flags, EvaluatorMode eval_mode, long long &sol_count, vector<IntVect> *subsol_coord = nullptr, vector<enumf> *subsol_dist = nullptr) { bool findsubsols = (subsol_coord != nullptr) && (subsol_dist != nullptr); // d = lattice dimension (note that it might decrease during preprocessing) int d = b.get_rows(); // n = dimension of the space int n = b.get_cols(); FPLLL_CHECK(d > 0 && n > 0, "shortestVector: empty matrix"); FPLLL_CHECK(d <= n, "shortestVector: number of vectors > size of the vectors"); // Sets the floating-point precision // Error bounds on GSO are valid if prec >= minprec double rho; int min_prec = gso_min_prec(rho, d, LLL_DEF_DELTA, LLL_DEF_ETA); int prec = max(53, min_prec + 10); int old_prec = Float::set_prec(prec); // Allocates space for vectors and matrices in constructors IntMatrix empty_mat; MatGSO<Integer, Float> gso(b, empty_mat, empty_mat, GSO_INT_GRAM); Float max_dist; Integer int_max_dist; Integer itmp1; // Computes the Gram-Schmidt orthogonalization in floating-point gso.update_gso(); gen_zero_vect(sol_coord, d); // If the last b_i* are too large, removes them to avoid an underflow int new_d = last_useful_index(gso.get_r_matrix()); if (new_d < d) { // FPLLL_TRACE("Ignoring the last " << d - new_d << " vector(s)"); d = new_d; } if (flags & SVP_DUAL) { max_dist = 1.0 / gso.get_r_exp(d - 1, d - 1); if (flags & SVP_VERBOSE) { cout << "max_dist = " << max_dist << endl; } } else { /* Computes a bound for the enumeration. This bound would work for an exact algorithm, but we will increase it later to ensure that the fp algorithm finds a solution */ get_basis_min(int_max_dist, b, 0, d); max_dist.set_z(int_max_dist, GMP_RNDU); } // Initializes the evaluator of solutions Evaluator<Float> *evaluator; if (method == SVPM_FAST) { evaluator = new FastEvaluator<Float>(d, gso.get_mu_matrix(), gso.get_r_matrix(), eval_mode, 0, findsubsols); } else if (method == SVPM_PROVED) { ExactEvaluator *p = new ExactEvaluator(d, b, gso.get_mu_matrix(), gso.get_r_matrix(), eval_mode, 0, findsubsols); p->int_max_dist = int_max_dist; evaluator = p; } else { FPLLL_ABORT("shortestVector: invalid evaluator type"); } evaluator->init_delta_def(prec, rho, true); if (!(flags & SVP_OVERRIDE_BND) && (eval_mode == EVALMODE_SV || method == SVPM_PROVED)) { Float ftmp1; bool result = evaluator->get_max_error_aux(max_dist, true, ftmp1); FPLLL_CHECK(result, "shortestVector: cannot compute an initial bound"); max_dist.add(max_dist, ftmp1, GMP_RNDU); } // Main loop of the enumeration enumerate_svp(d, gso, max_dist, *evaluator, pruning, flags); int result = RED_ENUM_FAILURE; if (eval_mode != EVALMODE_SV) { result = RED_SUCCESS; sol_count = evaluator->sol_count * 2; } else if (!evaluator->sol_coord.empty()) { /*Float fMaxError; validMaxError = evaluator->get_max_error(fMaxError); max_error = fMaxError.get_d(GMP_RNDU);*/ for (int i = 0; i < d; i++) { itmp1.set_f(evaluator->sol_coord[i]); sol_coord[i].add(sol_coord[i], itmp1); } result = RED_SUCCESS; } if (findsubsols) { subsol_coord->clear(); subsol_dist->clear(); subsol_dist->resize(evaluator->sub_sol_coord.size()); for (size_t i = 0; i < evaluator->sub_sol_coord.size(); ++i) { (*subsol_dist)[i] = evaluator->sub_sol_dist[i]; IntVect ss_c; for (size_t j = 0; j < evaluator->sub_sol_coord[i].size(); ++j) { itmp1.set_f(evaluator->sub_sol_coord[i][j]); ss_c.emplace_back(itmp1); } subsol_coord->emplace_back(std::move(ss_c)); } } delete evaluator; Float::set_prec(old_prec); return result; }