Example #1
0
/**
 * interface called from call_bkz() from main.cpp.
 */
int bkz_reduction(IntMatrix *B, IntMatrix *U, const BKZParam &param, 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;
}
Example #2
0
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;
}