Esempio n. 1
0
template <class ZT, class FT> void MatHouseholder<ZT, FT>::update_R_naively(int i)
{
  // This function try to strictly respect Algorithm 2 of [MSV'09].
  FPLLL_DEBUG_CHECK(i <= n_known_rows_naively);

  int j;

  // Set B in R_naively.
  if (enable_row_expo)
  {
    long max_expo = LONG_MIN;

    for (j = 0; j < n; j++)
    {
      b(i, j).get_f_exp(R_naively(i, j), tmp_col_expo[j]);
      max_expo = max(max_expo, tmp_col_expo[j]);
    }

    for (j = 0; j < n; j++)
      R_naively(i, j).mul_2si(R_naively(i, j), tmp_col_expo[j] - max_expo);

    row_expo_naively[i] = max_expo;
    FPLLL_DEBUG_CHECK(row_expo_naively[i] >= 0);
  }
  else
  {
    for (j = 0; j < n; j++)
      R_naively(i, j).set_z(b(i, j));
  }

  for (j = 0; j < i; j++)
  {
    // vj * ri[j..n]^T
    V_naively[j].dot_product(ftmp0, R_naively[i], j, n);

    //-vj * ri[j..n]^T
    ftmp0.neg(ftmp0);
    // ri[j..n] = ri[j..n] - (vj * ri[j..n]^T) * vj
    R_naively[i].addmul(V_naively[j], ftmp0, j, n);
    // ri[j] = sigma_naively[j] * ri[j]
    R_naively(i, j).mul(sigma_naively[j], R_naively(i, j));
  }

  // Here, ftmp2 is equal to s in [MSV, ISSAC'09].
  // Copy R_naively[i][i..n] in V_naively
  for (j = i; j < n; j++)
    V_naively(i, j) = R_naively(i, j);

  // sigma_naively[i] = sign(r[1])
  sigma_naively[i] = (R_naively(i, i).cmp(0.0) < 0) ? -1.0 : 1.0;
  R_naively[i].dot_product(ftmp2, R_naively[i], i, n);
  ftmp2.sqrt(ftmp2);
  ftmp2.mul(ftmp2, sigma_naively[i]);
  // Here, ftmp2 = sigma_naively[i] * ||r||

  // ftmp0 = (r[1] + ftmp2)
  ftmp0.add(R_naively(i, i), ftmp2);
  if (ftmp0.cmp(0.0) != 0)
  {
    if (i + 1 == n)
      ftmp1 = 0.0;
    else
      R_naively[i].dot_product(ftmp1, R_naively[i], i + 1, n);
    if (ftmp1.cmp(0.0) != 0)
    {
      // ftmp1 = (-sum(r[j]^2, j, 2, n-i+1)
      ftmp1.neg(ftmp1);

      // vi[1] = (-sum(r[j]^2, j, 2, n-i+1) / (r[1] + ftmp2)
      V_naively(i, i).div(ftmp1, ftmp0);

      ftmp2.neg(ftmp2);
      ftmp0.mul(ftmp2, V_naively(i, i));
      // Here, ftmp0 = -ftmp2 * vi[1]

      // ftmp0 = sqrt(-ftmp2 * vi[1])
      ftmp0.sqrt(ftmp0);

      V_naively[i].div(V_naively[i], i, n, ftmp0);

      R_naively(i, i).abs(ftmp2);
      for (j = i + 1; j < n; j++)
        R_naively(i, j) = 0.0;
    }
    else
    {
      if (R_naively(i, i).cmp(0.0) < 0)
        R_naively(i, i).neg(R_naively(i, i));

      V_naively(i, i) = 0.0;
      for (int k = i + 1; k < n; k++)
      {
        V_naively(i, k) = 0.0;
        R_naively(i, k) = 0.0;
      }
    }
  }
  else
  {
    for (int k = i; k < n; k++)
    {
      V_naively(i, k) = 0.0;
      R_naively(i, k) = 0.0;
    }
  }

  n_known_rows_naively++;
}
Esempio n. 2
0
// TODO: maybe add a variable available on DEBUG to verify in update_R(i, false) was done
// This function corresponds more or less to householder_v in hplll.
template <class ZT, class FT> void MatHouseholder<ZT, FT>::update_R_last(int i)
{
  // sigma[i] = sign(r[1])
  sigma[i] = (R(i, i).cmp(0.0) < 0) ? -1.0 : 1.0;
  // V(i, i) is used as a temporary variable. In the following, V(i, i) is always modified.
  if (i + 1 == n)
    ftmp3 = 0.0;
  else
  {
    // r^T * r (with first coefficient ignored)
    R[i].dot_product(ftmp3, R[i], i + 1, n);
  }
  ftmp1.mul(R(i, i), R(i, i));
  // ftmp1 = r^T * r
  ftmp1.add(ftmp1, ftmp3);

  if (ftmp1.cmp(0.0) != 0)
  {
    // ||r||
    ftmp2.sqrt(ftmp1);
    // s = sigma[i] * ||r|| = sigma[i] * sqrt(r * r^T)
    ftmp0.mul(sigma[i], ftmp2);
    ftmp1.add(R(i, i), ftmp0);
    // ftmp3 = (-sum(r[j]^2, j, 2, n-i+1)
    ftmp3.neg(ftmp3);
    // ftmp3 = (-sum(r[j]^2, j, 2, n-i+1) / (r[1] + s)
    ftmp3.div(ftmp3, ftmp1);
    // If ftmp3 = 0, then ftmp0 = 0 and then, divide by ftmp0 is not allowed
    if (ftmp3.cmp(0.0) != 0)
    {
      // ftmp0 = -sigma[i] * ||r||
      ftmp0.neg(ftmp0);
      // ftmp0 = -sigma[i] * ||r|| * (-sum(r[j]^2, j, 2, n-i+1) / (r[1] + s)
      ftmp0.mul(ftmp0, ftmp3);
      // ftmp0 = sqrt(-sigma[i] * ||r|| * (-sum(r[j]^2, j, 2, n-i+1) / (r[1] + s))
      ftmp0.sqrt(ftmp0);

#ifndef HOUSEHOLDER_PRECOMPUTE_INVERSE
      // V(i, i) =
      // ((-sum(r[j]^2, j, 2, n-i+1) / (r[1] + s)) / sqrt(-sigma[i] * ||r|| * (-sum(r[j]^2, j, 2,
      // n-i+1) / (r[1] + s))
      V(i, i).div(ftmp3, ftmp0);
      // R(i, i) = ||r||
      R(i, i) = ftmp2;

      V[i].div(R[i], i + 1, n, ftmp0);

#else   // HOUSEHOLDER_PRECOMPUTE_INVERSE
      ftmp0.div(1.0, ftmp0);
      // Here, ftmp0 = 1 / sqrt(-s * vi[1])
      V(i, i).mul(ftmp3, ftmp0);
      R(i, i) = ftmp2;

      // FIXME: not tested.
      V[i].mul(R[i], i + 1, n, ftmp0);

      R_inverse_diag[i].div(1.0, ftmp2);
#endif  // HOUSEHOLDER_PRECOMPUTE_INVERSE
        // Here, vi = vi / ftmp0 and ri[i..n] = (||r||, 0, 0, ..., 0)

#ifdef DEBUG
      // Setting R(i, k) to 0 is not neccessary since this value will be not used in HLLL.
      // However, in DEBUG, we must set to do not break test.
      for (int k = i + 1; k < n; k++)
        R(i, k) = 0.0;
#endif  // DEBUG
    }
    else
    {
      V(i, i) = 0.0;
      if (R(i, i).cmp(0.0) < 0)
        R(i, i).neg(R(i, i));

      // TODO: this is a row operation (from i + 1 to n).
      for (int k = i + 1; k < n; k++)
      {
        // if enable_row_expo, R can be not correct at some point of the computation
        FPLLL_DEBUG_CHECK(enable_row_expo ? 1 : R(i, k).is_zero());
        V(i, k) = 0.0;

// Setting R(i, k) to 0 is not neccessary since this value will be not used in HLLL.
// However, in DEBUG, we must set to do not break test.
#ifdef DEBUG
        R(i, k) = 0.0;
#endif  // DEBUG
      }

#ifdef HOUSEHOLDER_PRECOMPUTE_INVERSE
      R_inverse_diag[i].div(1.0, R(i, i));
#endif  // HOUSEHOLDER_PRECOMPUTE_INVERSE
    }
  }
  else
  {
    R(i, i) = 0.0;
    V(i, i) = 0.0;
    // The for loop can for(int k = i; k < n; k++) if the setting of R(i, k) is uncommented.
    // TODO: this is a row operation (from i + 1 to n).
    for (int k = i + 1; k < n; k++)
    {
      // if enable_row_expo, R can be not correct at some point of the computation
      FPLLL_DEBUG_CHECK(enable_row_expo ? 1 : R(i, k).is_zero());
      V(i, k) = 0.0;

// Setting R(i, k) to 0 is not neccessary since this value will be not used in HLLL.
// However, in DEBUG, we must set to do not break test.
#ifdef DEBUG
      R(i, k) = 0.0;
#endif  // DEBUG
    }

#ifdef HOUSEHOLDER_PRECOMPUTE_INVERSE
    // Result is inf.
    // TODO: set inf instead of doing the computation.
    R_inverse_diag[i].div(1.0, 0.0);
#endif  // HOUSEHOLDER_PRECOMPUTE_INVERSE
  }

  n_known_rows++;
}
Esempio n. 3
0
vector<Strategy> load_strategies_json(const std::string &filename)
{
  json js;
  {
    std::ifstream fs(filename);
    if (fs.fail())
      throw std::runtime_error("Cannot open strategies file.");
    fs >> js;
  }

  vector<Strategy> strategies;

  for(auto it = js.begin(); it != js.end(); ++it)
  {
    const json &j_strat = *it;
    const size_t block_size = j_strat["block_size"];
    FPLLL_DEBUG_CHECK(block_size < 4096); // some arbitrary upper limit

    // ensure to add this strategy in the right place
    while(strategies.size() <= block_size)
    {
      strategies.emplace_back();
    }

    Strategy strategy;
    strategy.block_size = block_size;

    if (j_strat.find("preprocessing_block_sizes") != j_strat.end())
    {
      for (auto p_it = j_strat["preprocessing_block_sizes"].begin(); p_it != j_strat["preprocessing_block_sizes"].end();
           ++p_it)
      {
        if ((*p_it).is_number())
        {
          strategy.preprocessing_block_sizes.emplace_back((*p_it).get<int>());
        }
        else
        {
          strategy.preprocessing_block_sizes.emplace_back((*p_it)["block_size"]);
        }
      }
    }

    if (j_strat.find("pruning_parameters") != j_strat.end())
    {
      for (auto p_it = j_strat["pruning_parameters"].begin();
           p_it != j_strat["pruning_parameters"].end(); ++p_it)
      {
        const json &j_prun = *p_it;
        Pruning pruning;
        pruning.radius_factor = j_prun[0];

        // fplll enforces that the first pruning coefficient is 1.0
        FPLLL_DEBUG_CHECK((double) j_prun[1][0] == 1.0);

        for (auto c_it = j_prun[1].begin(); c_it != j_prun[1].end(); ++c_it)
        {
          double c = (*c_it);
          pruning.coefficients.emplace_back(c);
        }
        pruning.probability = j_prun[2];
        FPLLL_DEBUG_CHECK(pruning.probability > 0.0 && pruning.probability <= 1.0);

        strategy.pruning_parameters.emplace_back(pruning);
      }
    }

    strategies[block_size] = std::move(strategy);
  }

  // finally, we make sure all strategies are sound
  for(auto it = strategies.begin(); it != strategies.end(); ++it) {
    if(it->pruning_parameters.size() == 0)
      it->pruning_parameters.emplace_back(Pruning());
  }

  return strategies;
}
Esempio n. 4
0
template <class ZT, class FT> void MatGSOGram<ZT, FT>::move_row(int old_r, int new_r)
{
  FPLLL_DEBUG_CHECK(!cols_locked);
  if (new_r < old_r)
  {
    FPLLL_DEBUG_CHECK(old_r < n_known_rows && !cols_locked);
    for (int i = new_r; i < n_known_rows; i++)
    {
      invalidate_gso_row(i, new_r);
    }
    rotate(gso_valid_cols.begin() + new_r, gso_valid_cols.begin() + old_r,
           gso_valid_cols.begin() + old_r + 1);
    mu.rotate_right(new_r, old_r);
    r.rotate_right(new_r, old_r);
    if (enable_transform)
    {
      u.rotate_right(new_r, old_r);
      if (enable_inverse_transform)
        u_inv_t.rotate_right(new_r, old_r);
    }
    if (enable_int_gram)
    {
      if (gptr == nullptr)
      {
        throw std::runtime_error("Error: gptr is equal to the nullpointer.");
      }
      gptr->rotate_gram_right(new_r, old_r, d);
    }
    else
    {
    }
  }

  else if (new_r > old_r)
  {
    for (int i = old_r; i < n_known_rows; i++)
    {
      invalidate_gso_row(i, old_r);
    }
    rotate(gso_valid_cols.begin() + old_r, gso_valid_cols.begin() + old_r + 1,
           gso_valid_cols.begin() + new_r + 1);
    mu.rotate_left(old_r, new_r);
    r.rotate_left(old_r, new_r);

    if (enable_transform)
    {
      u.rotate_left(old_r, new_r);
      if (enable_inverse_transform)
        u_inv_t.rotate_left(old_r, new_r);
    }

    if (enable_int_gram)
    {
      if (old_r < n_known_rows - 1)
      {
        if (gptr == nullptr)
        {
          throw std::runtime_error("Error: gptr is equal to the nullpointer.");
        }
        // gptr->rotate_gram_left(old_r, new_r, n_known_rows);
        gptr->rotate_gram_left(old_r, min(new_r, n_known_rows - 1), d);
      }
    }
    else
    {
    }
    if (new_r >= n_known_rows)
    {
      if (old_r < n_known_rows)
      {
        n_known_rows--;
        n_source_rows = n_known_rows;
      }
    }
  }
}
Esempio n. 5
0
vector<Strategy> load_strategies_json(const std::string &filename)
{
  json js;
  {
    std::ifstream fs(filename);
    if (fs.fail())
      throw std::runtime_error("Cannot open strategies file.");
    fs >> js;
  }

  vector<Strategy> strategies;

  for (auto it = js.begin(); it != js.end(); ++it)
  {
    const json &j_strat     = *it;
    const size_t block_size = j_strat["block_size"];
    FPLLL_DEBUG_CHECK(block_size < 4096);  // some arbitrary upper limit

    // ensure to add this strategy in the right place
    while (strategies.size() <= block_size)
    {
      strategies.emplace_back();
    }

    Strategy strategy;
    strategy.block_size = block_size;

    if (j_strat.find("preprocessing_block_sizes") != j_strat.end())
    {
      for (auto p_it = j_strat["preprocessing_block_sizes"].begin();
           p_it != j_strat["preprocessing_block_sizes"].end(); ++p_it)
      {
        if ((*p_it).is_number())
        {
          strategy.preprocessing_block_sizes.emplace_back((*p_it).get<int>());
        }
        else
        {
          strategy.preprocessing_block_sizes.emplace_back((*p_it)["block_size"]);
        }
      }
    }

    if (j_strat.find("pruning_parameters") != j_strat.end())
    {
      for (auto p_it = j_strat["pruning_parameters"].begin();
           p_it != j_strat["pruning_parameters"].end(); ++p_it)
      {
        const json &j_prun = *p_it;
        PruningParams pruning;
        pruning.gh_factor = j_prun[0];

        for (auto c_it = j_prun[1].begin(); c_it != j_prun[1].end(); ++c_it)
        {
          double c = (*c_it);
          pruning.coefficients.emplace_back(c);
        }
        pruning.expectation = j_prun[2];
        // TODO: don't hardcode success probability as metric
        pruning.metric = PRUNER_METRIC_PROBABILITY_OF_SHORTEST;
        FPLLL_DEBUG_CHECK(pruning.expectation > 0.0 && pruning.expectation <= 1.0);

        strategy.pruning_parameters.emplace_back(pruning);
      }
    }

    strategies[block_size] = std::move(strategy);
  }

  // finally, we make sure all strategies are sound
  for (auto it = strategies.begin(); it != strategies.end(); ++it)
  {
    if (it->pruning_parameters.size() == 0)
      it->pruning_parameters.emplace_back(PruningParams());
  }

  return strategies;
}