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++; }
// 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++; }
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; }
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; } } } }
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; }