int count_significance_digit(Float a) { for (int i = 0; i < 30; i++) { if (roundto(a, i) == a) { return i; } } return -1; }
void EnumerationDyn<FT>::prepare_enumeration(const vector<enumxt> &subtree, bool solvingsvp, bool subtree_reset) { is_svp = solvingsvp; enumf newdist = 0.0; k_end = d - subtree.size(); for (k = d - 1; k >= 0 && newdist <= maxdist; --k) { enumf newcenter = center_partsum[k]; if (k >= k_end) { // use subtree x[k] = subtree[k - k_end]; if (x[k] != 0) is_svp = false; for (int j = 0; j < k; ++j) center_partsum[j] -= x[k] * mut[j][k]; } else { if (dual) { for (int j = k + 1; j < k_end; ++j) newcenter -= alpha[j] * mut[k][j]; } else { for (int j = k + 1; j < k_end; ++j) newcenter -= x[j] * mut[k][j]; } roundto(x[k], newcenter); // newX = rint(newCenter) / lrint(newCenter) center[k] = newcenter; partdist[k] = newdist; dx[k] = ddx[k] = (((int)(newcenter >= x[k]) & 1) << 1) - 1; } if (!subtree_reset || k < k_end) { alpha[k] = x[k] - newcenter; newdist += alpha[k] * alpha[k] * rdiag[k]; } } if (!is_svp) { k_max = k_end; // The last non-zero coordinate of x will not stay positive } else { k_max = 0; x[0] = 1; // Excludes (0,...,0) from the enumeration } ++k; }
inline void EnumerationBase::enumerate_recursive( EnumerationBase::opts<kk, kk_start, dualenum, findsubsols, enable_reset>) { enumf alphak = x[kk] - center[kk]; enumf newdist = partdist[kk] + alphak * alphak * rdiag[kk]; if (!(newdist <= partdistbounds[kk])) return; ++nodes; alpha[kk] = alphak; if (findsubsols && newdist < subsoldists[kk]) { subsoldists[kk] = newdist; process_subsolution(kk, newdist); } if (kk == 0) { if (newdist > 0.0 || !is_svp) process_solution(newdist); } else if (enable_reset && kk < reset_depth) // in CVP, below the max GS vector, we reset the partial distance { reset(newdist, kk); return; } else { partdist[kk - 1] = newdist; if (dualenum) { for (int j = center_partsum_begin[kk]; j > kk - 1; --j) center_partsums[kk - 1][j] = center_partsums[kk - 1][j + 1] - alpha[j] * mut[kk - 1][j]; } else { for (int j = center_partsum_begin[kk]; j > kk - 1; --j) center_partsums[kk - 1][j] = center_partsums[kk - 1][j + 1] - x[j] * mut[kk - 1][j]; } if (center_partsum_begin[kk] > center_partsum_begin[kk - 1]) center_partsum_begin[kk - 1] = center_partsum_begin[kk]; center_partsum_begin[kk] = kk; center[kk - 1] = center_partsums[kk - 1][kk]; roundto(x[kk - 1], center[kk - 1]); dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1; } while (true) { FPLLL_TRACE("Level k=" << kk << " dist_k=" << partdist[kk] << " x_k=" << x[kk] << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[kk]); enumerate_recursive(opts<kk - 1, kk_start, dualenum, findsubsols, enable_reset>()); if (partdist[kk] != 0.0) { x[kk] += dx[kk]; ddx[kk] = -ddx[kk]; dx[kk] = ddx[kk] - dx[kk]; enumf alphak2 = x[kk] - center[kk]; enumf newdist2 = partdist[kk] + alphak2 * alphak2 * rdiag[kk]; if (!(newdist2 <= partdistbounds[kk])) return; ++nodes; alpha[kk] = alphak2; if (kk == 0) { if (newdist2 > 0.0 || !is_svp) process_solution(newdist2); } else { partdist[kk - 1] = newdist2; if (dualenum) center_partsums[kk - 1][kk - 1 + 1] = center_partsums[kk - 1][kk - 1 + 1 + 1] - alpha[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; else center_partsums[kk - 1][kk - 1 + 1] = center_partsums[kk - 1][kk - 1 + 1 + 1] - x[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; if (kk > center_partsum_begin[kk - 1]) center_partsum_begin[kk - 1] = kk; center[kk - 1] = center_partsums[kk - 1][kk - 1 + 1]; roundto(x[kk - 1], center[kk - 1]); dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1; } } else { ++x[kk]; enumf alphak2 = x[kk] - center[kk]; enumf newdist2 = partdist[kk] + alphak2 * alphak2 * rdiag[kk]; if (!(newdist2 <= partdistbounds[kk])) return; ++nodes; alpha[kk] = alphak2; if (kk == 0) { if (newdist2 > 0.0 || !is_svp) process_solution(newdist2); } else { partdist[kk - 1] = newdist2; if (dualenum) center_partsums[kk - 1][kk - 1 + 1] = center_partsums[kk - 1][kk - 1 + 1 + 1] - alpha[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; else center_partsums[kk - 1][kk - 1 + 1] = center_partsums[kk - 1][kk - 1 + 1 + 1] - x[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; if (kk > center_partsum_begin[kk - 1]) center_partsum_begin[kk - 1] = kk; center[kk - 1] = center_partsums[kk - 1][kk - 1 + 1]; roundto(x[kk - 1], center[kk - 1]); dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1; } } } }
template <bool dualenum, bool findsubsols, bool enable_reset> void EnumerationBase::enumerate_loop() { if (k >= k_end) return; for (int i = 0; i < k_end; ++i) { center_partsum_begin[i + 1] = k_end - 1; center_partsums[i][k_end] = center_partsum[i]; } partdist[k_end] = 0.0; // needed to make next_pos_up() work properly nodes -= k_end - k; k = k_end - 1; #ifdef FPLLL_WITH_RECURSIVE_ENUM enumerate_recursive_dispatch<dualenum, findsubsols, enable_reset>(k); return; #endif finished = false; while (!finished) { enumf alphak = x[k] - center[k]; enumf newdist = partdist[k] + alphak * alphak * rdiag[k]; FPLLL_TRACE("Level k=" << k << " dist_k=" << partdist[k] << " x_k=" << x[k] << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[k]); if (newdist <= partdistbounds[k]) { ++nodes; alpha[k] = alphak; if (findsubsols && newdist < subsoldists[k]) { subsoldists[k] = newdist; process_subsolution(k, newdist); } --k; if (k < 0) { if (newdist > 0.0 || !is_svp) process_solution(newdist); finished = !next_pos_up(); continue; } if (enable_reset && k < reset_depth) // in CVP, below the max GS vector, we reset the partial distance { reset(newdist, k); finished = !next_pos_up(); continue; } if (dualenum) { for (int j = center_partsum_begin[k + 1]; j > k; --j) center_partsums[k][j] = center_partsums[k][j + 1] - alpha[j] * mut[k][j]; } else { for (int j = center_partsum_begin[k + 1]; j > k; --j) center_partsums[k][j] = center_partsums[k][j + 1] - x[j] * mut[k][j]; } center_partsum_begin[k] = max(center_partsum_begin[k], center_partsum_begin[k + 1]); center_partsum_begin[k + 1] = k + 1; enumf newcenter = center_partsums[k][k + 1]; center[k] = newcenter; partdist[k] = newdist; roundto(x[k], newcenter); dx[k] = ddx[k] = (((int)(newcenter >= x[k]) & 1) << 1) - 1; } else { finished = !next_pos_up(); } } }