Пример #1
0
static int compute_min_prec(double &rho, int d, double delta, double eta, double epsilon,
                            MinPrecAlgo algo)
{
  int old_prec = Float::set_prec(53);
  Float f_minprec, f_rho, f_d, f_eta, f_delta, f_epsilon, tmp1, tmp2;

  // These four conversions are exact
  f_d       = static_cast<double>(d);
  f_eta     = eta;
  f_delta   = delta;
  f_epsilon = epsilon;
  if (algo == MINPREC_L2)
  {
    // eta - 0.5 is an exact fp operation
    if (f_epsilon > eta - 0.5)
      f_epsilon = eta - 0.5;
    tmp1        = 1.0;
    tmp1.sub(tmp1, f_delta, GMP_RNDD);
    if (f_epsilon > tmp1)
      f_epsilon = tmp1;
    // now fEpsilon <= min(epsilon, eta - 0.5, 1 - delta);
  }
  // Computes tmp1 >= (1 + eta) ^ 2 + epsilon
  tmp1 = 1.0;                       // exact
  tmp1.add(f_eta, tmp1, GMP_RNDU);  // >= 1 + eta
  tmp1.mul(tmp1, tmp1, GMP_RNDU);   // >= (1 + eta) ^ 2
  tmp1.add(tmp1, f_epsilon, GMP_RNDU);
  // Computes tmp2 <= delta - eta ^ 2
  tmp2.mul(f_eta, f_eta, GMP_RNDU);
  tmp2.sub(f_delta, tmp2, GMP_RNDD);
  FPLLL_CHECK(tmp2 > 0, "invalid LLL parameters, eta must be < sqrt(delta)");
  // Computes rho >= ((1 + eta) ^ 2 + epsilon) / (delta - eta ^ 2)
  f_rho.div(tmp1, tmp2, GMP_RNDU);
  rho = f_rho.get_d(GMP_RNDU);

  /* Computes minprec >= constant + 2 * log2(d) - log2(epsilon) + d * log2(rho)
     (constant = 5 for GSO, 10 for LLL) */
  tmp1.log(f_d, GMP_RNDU);         // >= log(d)
  tmp1.mul_2si(tmp1, 1);           // >= 2 * log(d)
  tmp2.log(f_epsilon, GMP_RNDD);   // <= log(epsilon) (<= 0)
  tmp1.sub(tmp1, tmp2, GMP_RNDU);  // >= 2 * log(d) - log(epsilon)
  tmp2.log(f_rho, GMP_RNDU);       // >= log(rho)
  tmp2.mul(f_d, tmp2, GMP_RNDU);   // >= d * log(rho)
  tmp1.add(tmp1, tmp2, GMP_RNDU);  // >= 2*log(d)-log(epsilon)+d*log(rho)
  tmp2 = 2.0;                      // exact
  tmp2.log(tmp2, GMP_RNDD);        // <= log(2)
  tmp1.div(tmp1, tmp2, GMP_RNDU);  // >= 2*log2(d)-log2(epsilon)+d*log2(rho)
  tmp2 = (algo == MINPREC_L2) ? 10.0 : 5.0;
  f_minprec.add(tmp1, tmp2, GMP_RNDU);
  int minprec = static_cast<int>(ceil(f_minprec.get_d(GMP_RNDU)));
  mpfr_free_cache();
  Float::set_prec(old_prec);
  return minprec;
}
Пример #2
0
void EnumerationDyn<FT>::enumerate(int first, int last, FT &fmaxdist, long fmaxdistexpo,
                                   const vector<FT> &target_coord, const vector<enumxt> &subtree,
                                   const vector<enumf> &pruning, bool _dual, bool subtree_reset)
{
  bool solvingsvp = target_coord.empty();
  dual            = _dual;
  pruning_bounds  = pruning;
  target          = target_coord;
  if (last == -1)
    last = _gso.d;
  d      = last - first;
  fx.resize(d);
  FPLLL_CHECK(d < maxdim, "enumerate: dimension is too high");
  FPLLL_CHECK((solvingsvp || !dual), "CVP for dual not implemented! What does that even mean? ");
  FPLLL_CHECK((subtree.empty() || !dual), "Subtree enumeration for dual not implemented!");

  resetflag = !_max_indices.empty();
  if (resetflag)
    reset_depth = _max_indices[last - subtree.size() - 1];

  if (solvingsvp)
  {
    for (int i          = 0; i < d; ++i)
      center_partsum[i] = 0.0;
  }
  else
  {
    for (int i          = 0; i < d; ++i)
      center_partsum[i] = target_coord[i + first].get_d();
  }

  FT fr, fmu, fmaxdistnorm;
  long rexpo, normexp = -1;
  for (int i = 0; i < d; ++i)
  {
    fr      = _gso.get_r_exp(i + first, i + first, rexpo);
    normexp = max(normexp, rexpo + fr.exponent());
  }
  fmaxdistnorm.mul_2si(fmaxdist, dual ? normexp - fmaxdistexpo : fmaxdistexpo - normexp);
  maxdist = fmaxdistnorm.get_d(GMP_RNDU);

  _evaluator.set_normexp(normexp);

  if (dual)
  {
    for (int i = 0; i < d; ++i)
    {
      fr = _gso.get_r_exp(i + first, i + first, rexpo);
      fr.mul_2si(fr, rexpo - normexp);
      rdiag[d - i - 1] = enumf(1.0) / fr.get_d();
    }
    for (int i = 0; i < d; ++i)
    {
      for (int j = i + 1; j < d; ++j)
      {
        _gso.get_mu(fmu, j + first, i + first);
        mut[d - j - 1][d - i - 1] = -fmu.get_d();
      }
    }
  }
  else
  {
    for (int i = 0; i < d; ++i)
    {
      fr = _gso.get_r_exp(i + first, i + first, rexpo);
      fr.mul_2si(fr, rexpo - normexp);
      rdiag[i] = fr.get_d();
    }
    for (int i = 0; i < d; ++i)
    {
      for (int j = i + 1; j < d; ++j)
      {
        _gso.get_mu(fmu, j + first, i + first);
        mut[i][j] = fmu.get_d();
      }
    }
  }

  subsoldists = rdiag;

  save_rounding();
  prepare_enumeration(subtree, solvingsvp, subtree_reset);
  do_enumerate();
  restore_rounding();

  fmaxdistnorm = maxdist;  // Exact

  fmaxdist.mul_2si(fmaxdistnorm, dual ? fmaxdistexpo - normexp : normexp - fmaxdistexpo);

  if (dual && !_evaluator.empty())
  {
    for (auto it = _evaluator.begin(), itend = _evaluator.end(); it != itend; ++it)
      reverse_by_swap(it->second, 0, d - 1);
  }
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
0
int closest_vector(IntMatrix &b, const IntVect &int_target, IntVect &sol_coord, int method, int flags)
{
  // 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, "closestVector: empty matrix");
  FPLLL_CHECK(d <= n, "closestVector: 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);
  FloatVect target_coord;
  Float max_dist;
  Integer itmp1;

  // Computes the Gram-Schmidt orthogonalization in floating-point
  gso.update_gso();
  gen_zero_vect(sol_coord, d);

  /* Applies Babai's algorithm. Because we use fp, it might be necessary to
      do it several times (if ||target|| >> ||b_i||) */
  FloatMatrix float_matrix(d, n);
  FloatVect target(n), babai_sol;
  IntVect int_new_target = int_target;

  for (int i = 0; i < d; i++)
    for (int j = 0; j < n; j++)
      float_matrix(i, j).set_z(b(i, j));

  for (int loop_idx = 0;; loop_idx++)
  {
    if (loop_idx >= 0x100 && ((loop_idx & (loop_idx - 1)) == 0))
      FPLLL_INFO("warning: possible infinite loop in Babai's algorithm");

    for (int i = 0; i < n; i++)
    {
      target[i].set_z(int_new_target[i]);
    }
    babai(float_matrix, gso.get_mu_matrix(), gso.get_r_matrix(), target, babai_sol);
    int idx;
    for (idx = 0; idx < d && babai_sol[idx] >= -1 && babai_sol[idx] <= 1; idx++)
    {
    }
    if (idx == d)
      break;

    for (int i = 0; i < d; i++)
    {
      itmp1.set_f(babai_sol[i]);
      sol_coord[i].add(sol_coord[i], itmp1);
      for (int j = 0; j < n; j++)
        int_new_target[j].submul(itmp1, b(i, j));
    }
  }
  // FPLLL_TRACE("BabaiSol=" << sol_coord);
  get_gscoords(float_matrix, gso.get_mu_matrix(), gso.get_r_matrix(), target, target_coord);

  /* Computes a very large bound to make the algorithm work
      until the first solution is found */
  max_dist = 0.0;
  for (int i = 1; i < d; i++)
  {
    // get_r_exp(i, i) = r(i, i) because gso is initialized without GSO_ROW_EXPO
    max_dist.add(max_dist, gso.get_r_exp(i, i));
  }

  vector<int> max_indices;
  if (method & CVPM_PROVED)
  {
    // For Exact CVP, we need to reset enum below depth with maximal r_i
    max_indices = vector<int>(d);
    int cur, max_index, previous_max_index;
    previous_max_index = max_index = d-1;
    Float max_val;

    while (max_index > 0)
    {
      max_val = gso.get_r_exp(max_index, max_index);
      for (cur = previous_max_index - 1 ; cur >= 0  ; --cur)
      {
        if (max_val <= gso.get_r_exp(cur, cur))
        {
          max_val = gso.get_r_exp(cur, cur);
          max_index = cur;
        }
      }
      for (cur = max_index ; cur < previous_max_index ; ++cur)
        max_indices[cur] = max_index;
      max_indices[previous_max_index] = previous_max_index;
      previous_max_index = max_index;
      --max_index;
    }
  }
  FPLLL_TRACE("max_indices " << max_indices);

  FastEvaluator<Float> evaluator(n, gso.get_mu_matrix(), gso.get_r_matrix(), EVALMODE_CV);

  // Main loop of the enumeration
  Enumeration<Float> enumobj(gso, evaluator, max_indices);
  enumobj.enumerate(0, d, max_dist, 0, target_coord);

  int result = RED_ENUM_FAILURE;
  if (!evaluator.sol_coord.empty())
  {
    FPLLL_TRACE("evaluator.sol_coord=" << evaluator.sol_coord);
    if (flags & CVP_VERBOSE)
      FPLLL_INFO("max_dist=" << max_dist);
    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;
  }

  Float::set_prec(old_prec);
  return result;
}