Update upstream source from tag 'upstream/5.4.2'
Update to upstream version '5.4.2'
with Debian dir f4f0b43bf1709af6fc5608657baca7410f104d33
Julien Puydt
1 year, 11 months ago
6 | 6 | - cron: '0 0 * * 0' # weekly |
7 | 7 | |
8 | 8 | env: |
9 | MAX_ENUM_DIM: 64 | |
10 | MAX_PARALLEL_ENUM_DIM: 20 | |
11 | 9 | JOBS: 2 |
10 | CONFIGURE_OPTS: --enable-recursive-enum --with-max-enum-dim=64 --with-max-parallel-enum-dim=64 | |
12 | 11 | |
13 | 12 | jobs: |
14 | 13 | linux: |
15 | 14 | runs-on: ubuntu-latest |
16 | ||
15 | strategy: | |
16 | matrix: | |
17 | include: | |
18 | - configure-options: --enable-recursive-enum --with-max-enum-dim=64 --with-max-parallel-enum-dim=64 | |
19 | - configure-options: --enable-recursive-enum --with-max-enum-dim=64 --with-max-parallel-enum-dim=0 | |
20 | - configure-options: --disable-recursive-enum --with-max-enum-dim=64 --with-max-parallel-enum-dim=0 | |
21 | ||
17 | 22 | steps: |
23 | - name: Echo Configure Options | |
24 | env: | |
25 | CONFIGURE_OPTS: ${{ matrix.configure-options }} | |
26 | run: echo $CONFIGURE_OPTS | |
18 | 27 | - name: Check out |
19 | 28 | uses: actions/checkout@v2 |
20 | 29 | - name: Install prerequisites |
23 | 32 | sudo DEBIAN_FRONTEND=noninteractive apt-get install autoconf automake libtool libgmp-dev libmpfr-dev libqd-dev |
24 | 33 | - name: Configure |
25 | 34 | run: | |
26 | ./autogen.sh | |
27 | ./configure --disable-static --with-max-enum-dim=$MAX_ENUM_DIM \ | |
28 | --with-max-parallel-enum-dim=$MAX_PARALLEL_ENUM_DIM | |
35 | autoreconf -i | |
36 | ./configure --disable-static $CONFIGURE_OPTS | |
29 | 37 | - name: Compile |
30 | 38 | run: make -j $JOBS |
31 | 39 | |
47 | 55 | - name: Configure |
48 | 56 | run: | |
49 | 57 | ./autogen.sh |
50 | ./configure --disable-static --with-max-enum-dim=$MAX_ENUM_DIM \ | |
51 | --with-max-parallel-enum-dim=$MAX_PARALLEL_ENUM_DIM | |
58 | ./configure --disable-static $CONFIGURE_OPTS | |
52 | 59 | - name: Compile |
53 | 60 | run: make -j $JOBS |
54 | 61 |
73 | 73 | /tests/test_enum |
74 | 74 | /tests/test_bkz_gram |
75 | 75 | /tests/test_svp_gram |
76 | /tests/test_counter | |
77 | /.cache/ |
37 | 37 | # could be handy for archiving the generated documentation or if some version |
38 | 38 | # control system is used. |
39 | 39 | |
40 | PROJECT_NUMBER = 5.4.1 | |
40 | PROJECT_NUMBER = 5.4.2 | |
41 | 41 | |
42 | 42 | # Using the PROJECT_BRIEF tag one can provide an optional one line description |
43 | 43 | # for a project that appears at the top of each page and should give viewer a |
16 | 16 | |
17 | 17 | @unpublished{fplll, |
18 | 18 | author = {The {FPLLL} development team}, |
19 | title = {{fplll}, a lattice reduction library, {Version}: 5.4.1}, | |
20 | year = 2021, | |
19 | title = {{fplll}, a lattice reduction library, {Version}: 5.4.2}, | |
20 | year = 2022, | |
21 | 21 | note = {Available at \url{https://github.com/fplll/fplll}}, |
22 | 22 | url = {https://github.com/fplll/fplll} |
23 | 23 | } |
408 | 408 | |
409 | 409 | - [json.hpp](fplll/io/json.hpp) is taken from https://github.com/nlohmann/json |
410 | 410 | |
411 | - This project has been supported by ERC Starting Grant ERC-2013-StG-335086-LATTAC. | |
411 | - This project has been supported by ERC Starting Grant ERC-2013-StG-335086-LATTAC, by the European Union PROMETHEUS project (Horizon 2020 Research and Innovation Program, grant 780701), by EPSRC grant EP/P009417/1 and by EPSRC grant EP/S020330/1. | |
412 | 412 | |
413 | 413 | # Contributing # |
414 | 414 |
0 | 0 | # -*- Autoconf -*- |
1 | 1 | # Process this file with autoconf to produce a configure script. |
2 | 2 | |
3 | AC_PREREQ(2.61) | |
4 | AC_INIT(fplll, 5.4.1) | |
3 | AC_PREREQ([2.69]) | |
4 | AC_INIT([fplll],[5.4.2]) | |
5 | 5 | AC_CONFIG_SRCDIR([fplll/fplll.cpp]) |
6 | 6 | AM_MAINTAINER_MODE([enable]) |
7 | AC_CANONICAL_TARGET | |
7 | 8 | |
8 | 9 | # cf http://comments.gmane.org/gmane.comp.sysutils.autoconf.general/15737 |
9 | 10 | |
18 | 19 | AM_INIT_AUTOMAKE([foreign subdir-objects]) |
19 | 20 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) |
20 | 21 | |
21 | AC_CONFIG_HEADER(config.h) | |
22 | AC_CONFIG_HEADERS([config.h]) | |
22 | 23 | |
23 | 24 | DEFAULT_CXXFLAGS="-O3 -Wall" |
24 | 25 | |
39 | 40 | # current, and set both revision and age to zero. |
40 | 41 | |
41 | 42 | FPLLL_LT_CURRENT=7 |
42 | FPLLL_LT_REVISION=0 | |
43 | FPLLL_LT_REVISION=1 | |
43 | 44 | FPLLL_LT_AGE=0 |
44 | 45 | |
45 | 46 | AC_SUBST(FPLLL_LT_CURRENT) |
49 | 50 | AC_PROG_INSTALL |
50 | 51 | |
51 | 52 | # Checks for programs. |
52 | AC_LANG_CPLUSPLUS | |
53 | AC_LANG([C++]) | |
53 | 54 | AC_PROG_CXX |
54 | 55 | AC_PROG_CC |
55 | 56 | AC_PROG_MAKE_SET |
138 | 139 | # the AC_SEARCH_LIBS macro works. |
139 | 140 | AC_SUBST(LIBQD_LIBS) |
140 | 141 | |
141 | # Checks for header files. | |
142 | AC_HEADER_STDC | |
143 | 142 | AC_CHECK_HEADERS([limits.h cstdio iostream string limits vector]) |
144 | 143 | |
145 | 144 | # Checks for typedefs, structures, and compiler characteristics. |
175 | 174 | AC_DEFINE([FPLLL_WITH_RECURSIVE_ENUM], [1], [recursive enumeration enabled])]) |
176 | 175 | |
177 | 176 | |
178 | max_parallel_enum_dim=80 | |
177 | max_parallel_enum_dim=120 | |
179 | 178 | AC_ARG_WITH(max-parallel-enum-dim, |
180 | 179 | AS_HELP_STRING([--with-max-parallel-enum-dim@<:@=DIM@:>@], |
181 | 180 | [Maximum supported parallel enumeration dimension (max=160, default=120, disable=0).]), |
123 | 123 | |
124 | 124 | install-data-hook: |
125 | 125 | echo "#include <fplll/fplll.h>" > "$(builddir)/fplll.h.root" |
126 | echo "using namespace fplll;" >> "$(builddir)/fplll.h.root" | |
127 | 126 | $(INSTALL) -m 644 "$(builddir)/fplll.h.root" "${DESTDIR}$(includedir)/fplll.h" |
128 | 127 | rm -f "$(builddir)/fplll.h.root" |
129 | 128 |
80 | 80 | { |
81 | 81 | json js; |
82 | 82 | { |
83 | std::ifstream fs(filename); | |
83 | std::ifstream fs(strategy_full_path(filename)); | |
84 | 84 | if (fs.fail()) |
85 | 85 | throw std::runtime_error("Cannot open strategies file."); |
86 | 86 | fs >> js; |
76 | 76 | << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[kk]); |
77 | 77 | enumerate_recursive(opts<kk - 1, kk_start, dualenum, findsubsols, enable_reset>()); |
78 | 78 | |
79 | if (partdist[kk] != 0.0) | |
79 | if (!is_svp || partdist[kk] != 0.0) | |
80 | 80 | { |
81 | 81 | x[kk] += dx[kk]; |
82 | 82 | ddx[kk] = -ddx[kk]; |
83 | 83 | dx[kk] = ddx[kk] - dx[kk]; |
84 | ||
85 | enumf alphak2 = x[kk] - center[kk]; | |
86 | enumf newdist2 = partdist[kk] + alphak2 * alphak2 * rdiag[kk]; | |
87 | if (!(newdist2 <= partdistbounds[kk])) | |
88 | return; | |
89 | ++nodes[kk]; | |
90 | alpha[kk] = alphak2; | |
91 | if (kk == 0) | |
92 | { | |
93 | if (newdist2 > 0.0 || !is_svp) | |
94 | process_solution(newdist2); | |
95 | } | |
84 | } | |
85 | else | |
86 | { | |
87 | ++x[kk]; | |
88 | } | |
89 | ||
90 | enumf alphak2 = x[kk] - center[kk]; | |
91 | enumf newdist2 = partdist[kk] + alphak2 * alphak2 * rdiag[kk]; | |
92 | if (!(newdist2 <= partdistbounds[kk])) | |
93 | return; | |
94 | ++nodes[kk]; | |
95 | alpha[kk] = alphak2; | |
96 | if (kk == 0) | |
97 | { | |
98 | if (newdist2 > 0.0 || !is_svp) | |
99 | process_solution(newdist2); | |
100 | } | |
101 | else | |
102 | { | |
103 | partdist[kk - 1] = newdist2; | |
104 | if (dualenum) | |
105 | center_partsums[kk - 1][kk - 1 + 1] = | |
106 | center_partsums[kk - 1][kk - 1 + 1 + 1] - alpha[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; | |
96 | 107 | else |
97 | { | |
98 | partdist[kk - 1] = newdist2; | |
99 | if (dualenum) | |
100 | center_partsums[kk - 1][kk - 1 + 1] = | |
101 | center_partsums[kk - 1][kk - 1 + 1 + 1] - alpha[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; | |
102 | else | |
103 | center_partsums[kk - 1][kk - 1 + 1] = | |
104 | center_partsums[kk - 1][kk - 1 + 1 + 1] - x[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; | |
105 | if (kk > center_partsum_begin[kk - 1]) | |
106 | center_partsum_begin[kk - 1] = kk; | |
107 | center[kk - 1] = center_partsums[kk - 1][kk - 1 + 1]; | |
108 | roundto(x[kk - 1], center[kk - 1]); | |
109 | dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1; | |
110 | } | |
111 | } | |
112 | else | |
113 | { | |
114 | ++x[kk]; | |
115 | ||
116 | enumf alphak2 = x[kk] - center[kk]; | |
117 | enumf newdist2 = partdist[kk] + alphak2 * alphak2 * rdiag[kk]; | |
118 | if (!(newdist2 <= partdistbounds[kk])) | |
119 | return; | |
120 | ++nodes[kk]; | |
121 | alpha[kk] = alphak2; | |
122 | if (kk == 0) | |
123 | { | |
124 | if (newdist2 > 0.0 || !is_svp) | |
125 | process_solution(newdist2); | |
126 | } | |
127 | else | |
128 | { | |
129 | partdist[kk - 1] = newdist2; | |
130 | if (dualenum) | |
131 | center_partsums[kk - 1][kk - 1 + 1] = | |
132 | center_partsums[kk - 1][kk - 1 + 1 + 1] - alpha[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; | |
133 | else | |
134 | center_partsums[kk - 1][kk - 1 + 1] = | |
135 | center_partsums[kk - 1][kk - 1 + 1 + 1] - x[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; | |
136 | if (kk > center_partsum_begin[kk - 1]) | |
137 | center_partsum_begin[kk - 1] = kk; | |
138 | center[kk - 1] = center_partsums[kk - 1][kk - 1 + 1]; | |
139 | roundto(x[kk - 1], center[kk - 1]); | |
140 | dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1; | |
141 | } | |
108 | center_partsums[kk - 1][kk - 1 + 1] = | |
109 | center_partsums[kk - 1][kk - 1 + 1 + 1] - x[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1]; | |
110 | if (kk > center_partsum_begin[kk - 1]) | |
111 | center_partsum_begin[kk - 1] = kk; | |
112 | center[kk - 1] = center_partsums[kk - 1][kk - 1 + 1]; | |
113 | roundto(x[kk - 1], center[kk - 1]); | |
114 | dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1; | |
142 | 115 | } |
143 | 116 | } |
144 | 117 | } |
71 | 71 | protected: |
72 | 72 | /* configuration */ |
73 | 73 | bool dual; |
74 | bool is_svp; | |
74 | bool is_svp; // only for SVP: exploit symmetry in enumeration to half search space | |
75 | 75 | bool resetflag; |
76 | 76 | |
77 | 77 | /* enumeration input */ |
155 | 155 | if (k >= k_end) |
156 | 156 | return false; |
157 | 157 | k_max = k; |
158 | ++x[k]; | |
158 | if (is_svp) | |
159 | { | |
160 | // only for SVP: break symmetry at the top non-zero coefficient | |
161 | ++x[k]; | |
162 | } | |
163 | else | |
164 | { | |
165 | x[k] += dx[k]; | |
166 | ddx[k] = -ddx[k]; | |
167 | dx[k] = ddx[k] - dx[k]; | |
168 | } | |
159 | 169 | } |
160 | 170 | return true; |
161 | 171 | } |
282 | 282 | vector<Z_NR<mpz_t>> new_sol, coord; |
283 | 283 | |
284 | 284 | gen_zero_vect(new_sol, n); |
285 | gen_zero_vect(coord, n); | |
285 | gen_zero_vect(coord, gso.get_rows_of_b()); | |
286 | 286 | new_sol_dist = 0; |
287 | 287 | |
288 | 288 | // Computes the distance between x and zero |
319 | 319 | vector<Z_NR<mpz_t>> new_sol, coord; |
320 | 320 | |
321 | 321 | gen_zero_vect(new_sol, n); |
322 | gen_zero_vect(coord, n); | |
322 | gen_zero_vect(coord, gso.get_rows_of_b()); | |
323 | 323 | new_sol_dist = 0; |
324 | 324 | |
325 | 325 | // Computes the distance between x[[offset,d)] and zero |
212 | 212 | ZT tmp; |
213 | 213 | sqnorm = 0; |
214 | 214 | vector_matrix_product(tmpvec, coordinates, b); |
215 | for (int j = 0; j < b.get_rows(); j++) | |
215 | for (size_t j = 0; j < tmpvec.size(); j++) | |
216 | 216 | { |
217 | 217 | tmp.mul(tmpvec[j], tmpvec[j]); |
218 | 218 | sqnorm.add(sqnorm, tmp); |
70 | 70 | * (in this case both must have the same number of rows). |
71 | 71 | * If u is initially the identity matrix, multiplying transform by the |
72 | 72 | * initial basis gives the current basis. |
73 | * In other words, u will contain the transformation matrix used on the basis b | |
74 | * that was used to obtain the current basis. | |
73 | 75 | * @param u_inv_t |
74 | 76 | * Inverse transform (should be empty, which disables the computation, or |
75 | 77 | * initialized with identity matrix). It works only if u is not empty. |
201 | 203 | * (lower triangular matrix) |
202 | 204 | * mu(i, j) = r(i, j) / ||b*_j||^2. |
203 | 205 | */ |
204 | const Matrix<FT> &get_mu_matrix() { return mu; } | |
206 | const Matrix<FT> &get_mu_matrix() const { return mu; } | |
205 | 207 | |
206 | 208 | /** |
207 | 209 | * Returns the r matrix |
208 | 210 | * Coefficients of the Gram Schmidt Orthogonalization |
209 | 211 | * (lower triangular matrix) |
210 | 212 | */ |
211 | const Matrix<FT> &get_r_matrix() { return r; } | |
213 | const Matrix<FT> &get_r_matrix() const { return r; } | |
212 | 214 | |
213 | 215 | /** |
214 | 216 | * Returns the g matrix (Z_NR version of r) |
215 | 217 | * Coefficients of the Gram Schmidt Orthogonalization |
216 | 218 | * (lower triangular matrix) |
217 | 219 | */ |
218 | const Matrix<ZT> &get_g_matrix() | |
220 | const Matrix<ZT> &get_g_matrix() const | |
219 | 221 | { |
220 | 222 | if (gptr == nullptr) |
221 | 223 | { |
233 | 235 | * The returned value is a reference to the coefficient of the internal |
234 | 236 | * matrix, which may change if the matrix is modified. |
235 | 237 | */ |
236 | inline const FT &get_mu_exp(int i, int j, long &expo); | |
237 | inline const FT &get_mu_exp(int i, int j); | |
238 | inline const FT &get_mu_exp(int i, int j, long &expo) const; | |
239 | inline const FT &get_mu_exp(int i, int j) const; | |
238 | 240 | |
239 | 241 | /** |
240 | 242 | * Returns f = (b_i, b*_j) / ||b*_j||^2. |
261 | 263 | * The returned value is a reference to the coefficient of the internal |
262 | 264 | * matrix, which may change if the matrix is modified |
263 | 265 | */ |
264 | inline const FT &get_r_exp(int i, int j, long &expo); | |
265 | inline const FT &get_r_exp(int i, int j); | |
266 | inline const FT &get_r_exp(int i, int j, long &expo) const; | |
267 | inline const FT &get_r_exp(int i, int j) const; | |
266 | 268 | |
267 | 269 | /** |
268 | 270 | * Returns f = (b_i, b*_j). |
645 | 647 | } |
646 | 648 | |
647 | 649 | template <class ZT, class FT> |
648 | inline const FT &MatGSOInterface<ZT, FT>::get_mu_exp(int i, int j, long &expo) | |
650 | inline const FT &MatGSOInterface<ZT, FT>::get_mu_exp(int i, int j, long &expo) const | |
649 | 651 | { |
650 | 652 | FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < i && j < gso_valid_cols[i] && |
651 | 653 | !in_row_op_range(i)); |
656 | 658 | return mu(i, j); |
657 | 659 | } |
658 | 660 | |
659 | template <class ZT, class FT> inline const FT &MatGSOInterface<ZT, FT>::get_mu_exp(int i, int j) | |
661 | template <class ZT, class FT> | |
662 | inline const FT &MatGSOInterface<ZT, FT>::get_mu_exp(int i, int j) const | |
660 | 663 | { |
661 | 664 | FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < i && j < gso_valid_cols[i] && |
662 | 665 | !in_row_op_range(i)); |
674 | 677 | } |
675 | 678 | |
676 | 679 | template <class ZT, class FT> |
677 | inline const FT &MatGSOInterface<ZT, FT>::get_r_exp(int i, int j, long &expo) | |
680 | inline const FT &MatGSOInterface<ZT, FT>::get_r_exp(int i, int j, long &expo) const | |
678 | 681 | { |
679 | 682 | FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < gso_valid_cols[i] && |
680 | 683 | !in_row_op_range(i)); |
685 | 688 | return r(i, j); |
686 | 689 | } |
687 | 690 | |
688 | template <class ZT, class FT> inline const FT &MatGSOInterface<ZT, FT>::get_r_exp(int i, int j) | |
691 | template <class ZT, class FT> | |
692 | inline const FT &MatGSOInterface<ZT, FT>::get_r_exp(int i, int j) const | |
689 | 693 | { |
690 | 694 | FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < gso_valid_cols[i] && |
691 | 695 | !in_row_op_range(i)); |
26 | 26 | * * |
27 | 27 | \*********************************************************************************/ |
28 | 28 | |
29 | // this file is slightly modified for fplll to use specialized header guards and namespace | |
30 | ||
31 | #ifndef FPLLL_THREAD_POOL_HPP | |
32 | #define FPLLL_THREAD_POOL_HPP | |
29 | #ifndef THREAD_POOL_HPP | |
30 | #define THREAD_POOL_HPP | |
33 | 31 | |
34 | 32 | #include <cstdint> |
35 | 33 | #include <memory> |
43 | 41 | #include <future> |
44 | 42 | #include <atomic> |
45 | 43 | |
46 | ||
47 | #include <fplll/defs.h> | |
48 | FPLLL_BEGIN_NAMESPACE | |
49 | ||
50 | 44 | /*************************** example usage ***************************************\ |
51 | 45 | grep "^//test.cpp" thread_pool.hpp -A33 > test.cpp |
52 | 46 | g++ -std=c++11 -o test test.cpp -pthread -lpthread |
204 | 198 | |
205 | 199 | inline void thread_pool::push(const std::function<void()>& f) |
206 | 200 | { |
207 | std::unique_lock<std::mutex> lock(_mutex); | |
208 | _tasks.emplace(f); | |
201 | { | |
202 | std::unique_lock<std::mutex> lock(_mutex); | |
203 | _tasks.emplace(f); | |
204 | } | |
209 | 205 | _condition.notify_one(); |
210 | 206 | } |
211 | 207 | |
212 | 208 | inline void thread_pool::push(std::function<void()>&& f) |
213 | 209 | { |
214 | std::unique_lock<std::mutex> lock(_mutex); | |
215 | _tasks.emplace(std::move(f)); | |
210 | { | |
211 | std::unique_lock<std::mutex> lock(_mutex); | |
212 | _tasks.emplace(std::move(f)); | |
213 | } | |
216 | 214 | _condition.notify_one(); |
217 | 215 | } |
218 | 216 | |
231 | 229 | { |
232 | 230 | if (threads < 1 || threads > int(_threads.size())+1) |
233 | 231 | threads = int(_threads.size())+1; |
234 | for (int i = 0; i < threads; ++i) | |
235 | this->push(f); | |
236 | this->wait_work(); | |
232 | { | |
233 | std::unique_lock<std::mutex> lock(_mutex); | |
234 | for (int i = 0; i < threads-1; ++i) | |
235 | _tasks.emplace(f); | |
236 | } | |
237 | _condition.notify_all(); | |
238 | f(); | |
239 | this->wait_sleep(); | |
237 | 240 | } |
238 | 241 | |
239 | 242 | inline void thread_pool::run(const std::function<void(int)>& f, int threads) |
240 | 243 | { |
241 | 244 | if (threads < 1 || threads > int(_threads.size())+1) |
242 | 245 | threads = int(_threads.size())+1; |
243 | for (int i = 0; i < threads; ++i) | |
244 | this->push( [f,i](){f(i);} ); | |
245 | this->wait_work(); | |
246 | { | |
247 | std::unique_lock<std::mutex> lock(_mutex); | |
248 | for (int i = 0; i < threads-1; ++i) | |
249 | _tasks.emplace( [=](){f(i);} ); | |
250 | } | |
251 | _condition.notify_all(); | |
252 | f(threads-1); | |
253 | this->wait_sleep(); | |
246 | 254 | } |
247 | 255 | |
248 | 256 | inline void thread_pool::run(const std::function<void(int,int)>& f, int threads) |
249 | 257 | { |
250 | 258 | if (threads < 1 || threads > int(_threads.size())+1) |
251 | 259 | threads = int(_threads.size())+1; |
252 | for (int i = 0; i < threads; ++i) | |
253 | this->push( [f,i,threads](){f(i,threads);} ); | |
254 | this->wait_work(); | |
260 | { | |
261 | std::unique_lock<std::mutex> lock(_mutex); | |
262 | for (int i = 0; i < threads-1; ++i) | |
263 | _tasks.emplace( [=](){f(i,threads);} ); | |
264 | } | |
265 | _condition.notify_all(); | |
266 | f(threads-1,threads); | |
267 | this->wait_sleep(); | |
255 | 268 | } |
256 | 269 | |
257 | 270 | inline void thread_pool::resize(std::size_t nrthreads) |
337 | 350 | if (++_i >= _count) |
338 | 351 | { |
339 | 352 | _i = 0; |
353 | lock.unlock(); | |
340 | 354 | _condition.notify_all(); |
341 | 355 | } |
342 | 356 | else |
347 | 361 | |
348 | 362 | } // namespace thread_pool |
349 | 363 | |
350 | FPLLL_END_NAMESPACE | |
351 | ||
352 | #endif // FPLLL_THREAD_POOL_HPP | |
364 | #endif // THREAD_POOL_HPP |
35 | 35 | * needed). |
36 | 36 | */ |
37 | 37 | LLLReduction(MatGSOInterface<ZT, FT> &m, double delta, double eta, int flags); |
38 | ||
39 | 38 | #ifdef FPLLL_WITH_LONG_DOUBLE |
40 | 39 | ~LLLReduction() { LDConvHelper::free(); } |
41 | 40 | #endif |
42 | ||
43 | 41 | /** |
44 | 42 | @brief LLL reduction. |
45 | 43 |
247 | 247 | ZZ_mat<mpz_t> u; |
248 | 248 | bool with_coord = strchr(format, 'c') != NULL; |
249 | 249 | bool with_coord_std = strchr(format, 's') != NULL; |
250 | int flags = SVP_DEFAULT | (o.verbose ? SVP_VERBOSE : 0); | |
251 | 250 | int flagsLLL = LLL_DEFAULT | (o.verbose ? LLL_VERBOSE : 0); |
251 | int flags; | |
252 | 252 | int status; |
253 | 253 | |
254 | 254 | if (!o.no_lll) |
269 | 269 | } |
270 | 270 | |
271 | 271 | if (target.empty()) |
272 | { | |
273 | flags = SVP_DEFAULT | (o.verbose ? SVP_VERBOSE : 0); | |
272 | 274 | status = shortest_vector(b, sol_coord, SVPM_PROVED, flags); |
275 | } | |
273 | 276 | else |
274 | status = closest_vector(b, target, sol_coord, flags); | |
277 | { | |
278 | flags = CVP_DEFAULT | (o.verbose ? CVP_VERBOSE : 0); | |
279 | status = closest_vector(b, target, sol_coord, CVPM_PROVED, flags); | |
280 | } | |
275 | 281 | |
276 | 282 | if (status != RED_SUCCESS) |
277 | 283 | { |
28 | 28 | */ |
29 | 29 | inline FP_NR<F>(); |
30 | 30 | inline FP_NR<F>(const FP_NR<F> &f); |
31 | inline ~FP_NR<F>(); | |
31 | inline ~FP_NR(); | |
32 | 32 | inline FP_NR<F>(const double d) : FP_NR<F>() { *this = d; }; |
33 | 33 | inline FP_NR<F>(const char *s) : FP_NR<F>() { *this = s; }; |
34 | 34 |
23 | 23 | /** |
24 | 24 | * Constructors. |
25 | 25 | */ |
26 | inline Z_NR<Z>(); | |
27 | inline Z_NR<Z>(const Z_NR<Z> &z); | |
28 | inline Z_NR<Z>(const Z &z); | |
29 | inline ~Z_NR<Z>(); | |
26 | inline Z_NR(); | |
27 | inline Z_NR(const Z_NR<Z> &z); | |
28 | inline Z_NR(const Z &z); | |
29 | inline ~Z_NR(); | |
30 | 30 | |
31 | 31 | /** get data */ |
32 | 32 | |
235 | 235 | */ |
236 | 236 | #ifdef FPLLL_WITH_LONG_DOUBLE |
237 | 237 | |
238 | // Thread_local variables for doing numeric conversions. | |
239 | // These are global to replace their previous usage, but member variables | |
240 | // cannot be thread local and so they're declared at this scope. | |
241 | // NOTE: these are extern because these can only have one definition. | |
242 | // These are defined in util.cpp | |
243 | extern thread_local mpfr_t temp_mpfr; | |
244 | extern thread_local bool temp_mpfr_initialized; | |
245 | ||
238 | 246 | class LDConvHelper |
239 | 247 | { |
240 | 248 | public: |
242 | 250 | static long double mpz_get_ld(const mpz_t op) |
243 | 251 | { |
244 | 252 | init_temp(); |
245 | mpfr_set_z(temp, op, GMP_RNDN); | |
246 | return mpfr_get_ld(temp, GMP_RNDN); // exact | |
253 | mpfr_set_z(temp_mpfr, op, GMP_RNDN); | |
254 | return mpfr_get_ld(temp_mpfr, GMP_RNDN); // exact | |
247 | 255 | } |
248 | 256 | |
249 | 257 | static void free() { free_temp(); } |
255 | 263 | static long double mpz_get_ld_2exp(long *exp, const mpz_t op) |
256 | 264 | { |
257 | 265 | init_temp(); |
258 | mpfr_set_z(temp, op, GMP_RNDN); | |
259 | return mpfr_get_ld_2exp(exp, temp, GMP_RNDN); // exact | |
266 | mpfr_set_z(temp_mpfr, op, GMP_RNDN); | |
267 | return mpfr_get_ld_2exp(exp, temp_mpfr, GMP_RNDN); // exact | |
260 | 268 | } |
261 | 269 | |
262 | 270 | /** Sets the value of rop from op. */ |
263 | 271 | static void mpz_set_ld(mpz_t rop, long double op) |
264 | 272 | { |
265 | 273 | init_temp(); |
266 | mpfr_set_ld(temp, op, GMP_RNDN); // exact | |
267 | mpfr_get_z(rop, temp, GMP_RNDN); | |
274 | mpfr_set_ld(temp_mpfr, op, GMP_RNDN); // exact | |
275 | mpfr_get_z(rop, temp_mpfr, GMP_RNDN); | |
268 | 276 | } |
269 | 277 | |
270 | 278 | private: |
271 | 279 | static inline void init_temp() |
272 | 280 | { |
273 | if (!temp_initialized) | |
281 | if (!temp_mpfr_initialized) | |
274 | 282 | { |
275 | mpfr_init2(temp, numeric_limits<long double>::digits); | |
276 | temp_initialized = true; | |
283 | mpfr_init2(temp_mpfr, numeric_limits<long double>::digits); | |
284 | temp_mpfr_initialized = true; | |
277 | 285 | } |
278 | 286 | } |
279 | 287 | |
280 | 288 | static inline void free_temp() |
281 | 289 | { |
282 | if (temp_initialized) | |
290 | if (temp_mpfr_initialized) | |
283 | 291 | { |
284 | mpfr_clear(temp); | |
285 | temp_initialized = false; | |
292 | mpfr_clear(temp_mpfr); | |
293 | temp_mpfr_initialized = false; | |
286 | 294 | } |
287 | 295 | } |
288 | ||
289 | // These static members are initialized in util.cpp | |
290 | static mpfr_t temp; | |
291 | static bool temp_initialized; | |
292 | 296 | }; |
293 | 297 | |
294 | 298 | #endif |
26 | 26 | MINPREC_L2 |
27 | 27 | }; |
28 | 28 | |
29 | /* State of LDConvHelper (declared in nr.h, must be defined in exactly one | |
30 | source file) */ | |
29 | /* | |
30 | Helper variables for LDConvHelper (declared in nr_Z.inl, must be defined in exactly | |
31 | one source file) | |
32 | */ | |
31 | 33 | #ifdef FPLLL_WITH_LONG_DOUBLE |
32 | mpfr_t LDConvHelper::temp; | |
33 | bool LDConvHelper::temp_initialized = false; | |
34 | thread_local mpfr_t temp_mpfr; | |
35 | thread_local bool temp_mpfr_initialized{false}; | |
34 | 36 | #endif |
35 | 37 | |
36 | 38 | /* State of the random generator (declared in nr.h, must be defined in exactly |
40 | 40 | void vector_matrix_product(vector<ZT> &result, const vector<ZT> &x, const Matrix<ZT> &m) |
41 | 41 | { |
42 | 42 | int nrows = m.get_rows(), ncols = m.get_cols(); |
43 | FPLLL_CHECK(x.size() == (unsigned int)nrows, "vector_matrix_product(): dimensions do not match!"); | |
43 | 44 | gen_zero_vect(result, ncols); |
44 | 45 | for (int i = 0; i < nrows; i++) |
45 | 46 | for (int j = 0; j < ncols; j++) |
52 | 53 | void vector_matrix_product(NumVect<ZT> &result, const NumVect<ZT> &x, const Matrix<ZT> &m) |
53 | 54 | { |
54 | 55 | int nrows = m.get_rows(), ncols = m.get_cols(); |
56 | FPLLL_CHECK(x.size() == nrows, "vector_matrix_product(): dimensions do not match!"); | |
55 | 57 | result.gen_zero(ncols); |
56 | 58 | for (int i = 0; i < nrows; i++) |
57 | 59 | for (int j = 0; j < ncols; j++) |
24 | 24 | /* The matrix b must not be modified before calling lll(). |
25 | 25 | lll() must be called only once. */ |
26 | 26 | |
27 | /** | |
28 | * @brief Wrapper. This class provides an externally callable API for LLL reducing some basis ``b``. | |
29 | * This class forcibly instantiates some template declarations (see FPLLL_DECLARE_LLL(T) for more | |
30 | * information at the bottom of this class) and provides an interface for calling provable, | |
31 | * heuristic and fast variants of both LLL and HLLL. | |
32 | * | |
33 | * User note: all of the parameters passed into this class are non-const references. Thus, this | |
34 | * class may overwrite these variables. | |
35 | * | |
36 | * In particular, the methods in this class typically | |
37 | * over-write the parameter ``u`` with the transformation matrix applied to ``b`` to produce LLL(B). | |
38 | * In other words, let C = LLL(B). Then we can write C = U B for some unimodular transformation | |
39 | * matrix U. For this reason, ``u`` should either be an empty matrix or the identity matrix when it | |
40 | * is passed in to this function, so that no information is lost. | |
41 | * | |
42 | * Similarly, the parameter ``u_inv`` will contain the inverse matrix ``u ^ -1``. | |
43 | * This allows you to recover the original basis ``b`` by multiplying ``C`` by ``u_inv``. | |
44 | * Note that all operations on this object are carried out on the transpose of this matrix | |
45 | * (see gso_interface.h) for speed: hence the discrepancy between the names (see the lll_reduction | |
46 | * method in wraper.cpp for this). This and other such behaviour on these parameters is described in | |
47 | * some detail in gso_interface.h. | |
48 | */ | |
27 | 49 | class Wrapper |
28 | 50 | { |
29 | 51 | public: |
15 | 15 | # The second argument, if specified, indicates whether you insist on an |
16 | 16 | # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. |
17 | 17 | # -std=c++11). If neither is specified, you get whatever works, with |
18 | # preference for an extended mode. | |
18 | # preference for no added switch, and then for an extended mode. | |
19 | 19 | # |
20 | 20 | # The third argument, if specified 'mandatory' or if left unspecified, |
21 | 21 | # indicates that baseline support for the specified C++ standard is |
34 | 34 | # Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu> |
35 | 35 | # Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com> |
36 | 36 | # Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com> |
37 | # Copyright (c) 2020 Jason Merrill <jason@redhat.com> | |
37 | 38 | # |
38 | 39 | # Copying and distribution of this file, with or without modification, are |
39 | 40 | # permitted in any medium without royalty provided the copyright notice |
40 | 41 | # and this notice are preserved. This file is offered as-is, without any |
41 | 42 | # warranty. |
42 | 43 | |
43 | #serial 11 | |
44 | #serial 12 | |
44 | 45 | |
45 | 46 | dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro |
46 | 47 | dnl (serial version number 13). |
60 | 61 | [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) |
61 | 62 | AC_LANG_PUSH([C++])dnl |
62 | 63 | ac_success=no |
64 | ||
65 | m4_if([$2], [], [dnl | |
66 | AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, | |
67 | ax_cv_cxx_compile_cxx$1, | |
68 | [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], | |
69 | [ax_cv_cxx_compile_cxx$1=yes], | |
70 | [ax_cv_cxx_compile_cxx$1=no])]) | |
71 | if test x$ax_cv_cxx_compile_cxx$1 = xyes; then | |
72 | ac_success=yes | |
73 | fi]) | |
63 | 74 | |
64 | 75 | m4_if([$2], [noext], [], [dnl |
65 | 76 | if test x$ac_success = xno; then |
13 | 13 | # flags that are needed. (The user can also force certain compiler |
14 | 14 | # flags/libs to be tested by setting these environment variables.) |
15 | 15 | # |
16 | # Also sets PTHREAD_CC to any special C compiler that is needed for | |
17 | # multi-threaded programs (defaults to the value of CC otherwise). (This | |
18 | # is necessary on AIX to use the special cc_r compiler alias.) | |
16 | # Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is | |
17 | # needed for multi-threaded programs (defaults to the value of CC | |
18 | # respectively CXX otherwise). (This is necessary on e.g. AIX to use the | |
19 | # special cc_r/CC_r compiler alias.) | |
19 | 20 | # |
20 | 21 | # NOTE: You are assumed to not only compile your program with these flags, |
21 | 22 | # but also to link with them as well. For example, you might link with |
22 | 23 | # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS |
24 | # $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS | |
23 | 25 | # |
24 | 26 | # If you are only building threaded programs, you may wish to use these |
25 | 27 | # variables in your default LIBS, CFLAGS, and CC: |
26 | 28 | # |
27 | 29 | # LIBS="$PTHREAD_LIBS $LIBS" |
28 | 30 | # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" |
31 | # CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" | |
29 | 32 | # CC="$PTHREAD_CC" |
33 | # CXX="$PTHREAD_CXX" | |
30 | 34 | # |
31 | 35 | # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant |
32 | 36 | # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to |
82 | 86 | # modified version of the Autoconf Macro, you may extend this special |
83 | 87 | # exception to the GPL to apply to your modified version as well. |
84 | 88 | |
85 | #serial 27 | |
89 | #serial 30 | |
86 | 90 | |
87 | 91 | AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) |
88 | 92 | AC_DEFUN([AX_PTHREAD], [ |
89 | AC_REQUIRE([AC_CANONICAL_HOST]) | |
93 | AC_REQUIRE([AC_CANONICAL_TARGET]) | |
90 | 94 | AC_REQUIRE([AC_PROG_CC]) |
91 | 95 | AC_REQUIRE([AC_PROG_SED]) |
92 | 96 | AC_LANG_PUSH([C]) |
104 | 108 | ax_pthread_save_CFLAGS="$CFLAGS" |
105 | 109 | ax_pthread_save_LIBS="$LIBS" |
106 | 110 | AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) |
111 | AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"]) | |
107 | 112 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" |
108 | 113 | LIBS="$PTHREAD_LIBS $LIBS" |
109 | 114 | AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) |
152 | 157 | # --thread-safe: KAI C++ |
153 | 158 | # pthread-config: use pthread-config program (for GNU Pth library) |
154 | 159 | |
155 | case $host_os in | |
160 | case $target_os in | |
156 | 161 | |
157 | 162 | freebsd*) |
158 | 163 | |
242 | 247 | # definitions is, on some systems, a strong hint that pthreads support is |
243 | 248 | # correctly enabled |
244 | 249 | |
245 | case $host_os in | |
250 | case $target_os in | |
246 | 251 | darwin* | hpux* | linux* | osf* | solaris*) |
247 | 252 | ax_pthread_check_macro="_REENTRANT" |
248 | 253 | ;; |
385 | 390 | # step |
386 | 391 | ax_pthread_save_ac_link="$ac_link" |
387 | 392 | ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' |
388 | ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` | |
393 | ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"` | |
389 | 394 | ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" |
390 | 395 | ax_pthread_save_CFLAGS="$CFLAGS" |
391 | 396 | for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do |
444 | 449 | AC_CACHE_CHECK([whether more special flags are required for pthreads], |
445 | 450 | [ax_cv_PTHREAD_SPECIAL_FLAGS], |
446 | 451 | [ax_cv_PTHREAD_SPECIAL_FLAGS=no |
447 | case $host_os in | |
452 | case $target_os in | |
448 | 453 | solaris*) |
449 | 454 | ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" |
450 | 455 | ;; |
474 | 479 | |
475 | 480 | # More AIX lossage: compile with *_r variant |
476 | 481 | if test "x$GCC" != "xyes"; then |
477 | case $host_os in | |
482 | case $target_os in | |
478 | 483 | aix*) |
479 | 484 | AS_CASE(["x/$CC"], |
480 | 485 | [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], |
481 | 486 | [#handle absolute path differently from PATH based program lookup |
482 | 487 | AS_CASE(["x$CC"], |
483 | 488 | [x/*], |
484 | [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], | |
485 | [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) | |
489 | [ | |
490 | AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"]) | |
491 | AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])]) | |
492 | ], | |
493 | [ | |
494 | AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC]) | |
495 | AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])]) | |
496 | ] | |
497 | ) | |
498 | ]) | |
486 | 499 | ;; |
487 | 500 | esac |
488 | 501 | fi |
489 | 502 | fi |
490 | 503 | |
491 | 504 | test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" |
505 | test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" | |
492 | 506 | |
493 | 507 | AC_SUBST([PTHREAD_LIBS]) |
494 | 508 | AC_SUBST([PTHREAD_CFLAGS]) |
495 | 509 | AC_SUBST([PTHREAD_CC]) |
510 | AC_SUBST([PTHREAD_CXX]) | |
496 | 511 | |
497 | 512 | # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: |
498 | 513 | if test "x$ax_pthread_ok" = "xyes"; then |
30 | 30 | lattices/example_cvp_out3 \ |
31 | 31 | lattices/example_cvp_out4 \ |
32 | 32 | lattices/example_cvp_out5 \ |
33 | lattices/example_list_cvp_in_lattice \ | |
33 | 34 | lattices/grammatrix_dimension4 \ |
34 | 35 | lattices/grammatrix_dimension4_out \ |
35 | 36 | lattices/grammatrix_dimension7 \ |
36 | lattices/grammatrix_dimension7_out | |
37 | lattices/grammatrix_dimension7_out | |
37 | 38 | |
38 | 39 | # include TOPBUILDIR for fplll_config.h |
39 | 40 | AM_CPPFLAGS = -I$(TOPSRCDIR) -I$(TOPSRCDIR)/fplll -I$(TOPBUILDDIR) -DTESTDATADIR=\"$(TOPSRCDIR)/\" |
0 | [[8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
1 | [4 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
2 | [4 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
3 | [4 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
4 | [4 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
5 | [4 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
6 | [4 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
7 | [2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
8 | [4 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
9 | [4 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
10 | [4 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0] | |
11 | [2 2 2 2 0 0 0 0 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0] | |
12 | [4 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0] | |
13 | [2 2 0 0 2 2 0 0 2 2 0 0 2 2 0 0 0 0 0 0 0 0 0 0] | |
14 | [2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0] | |
15 | [2 0 0 2 2 0 0 2 2 0 0 2 2 0 0 2 0 0 0 0 0 0 0 0] | |
16 | [4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0] | |
17 | [2 0 2 0 2 0 0 2 2 2 0 0 0 0 0 0 2 2 0 0 0 0 0 0] | |
18 | [2 0 0 2 2 2 0 0 2 0 2 0 0 0 0 0 2 0 2 0 0 0 0 0] | |
19 | [2 2 0 0 2 0 2 0 2 0 0 2 0 0 0 0 2 0 0 2 0 0 0 0] | |
20 | [0 2 2 2 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0] | |
21 | [0 0 0 0 0 0 0 0 2 2 0 0 2 2 0 0 2 2 0 0 2 2 0 0] | |
22 | [0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0] | |
23 | [-3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]] |
14 | 14 | |
15 | 15 | #include <cstring> |
16 | 16 | #include <fplll/fplll.h> |
17 | #include <test_utils.h> | |
17 | 18 | |
18 | 19 | using namespace fplll; |
19 | 20 | |
41 | 42 | { |
42 | 43 | return 0; |
43 | 44 | } |
45 | } | |
46 | ||
47 | /** | |
48 | @brief Test if list_CVP via enumeration function returns the correct amount of vectors | |
49 | @return | |
50 | */ | |
51 | ||
52 | template <class FT> int test_list_cvp() | |
53 | { | |
54 | ZZ_mat<mpz_t> u; | |
55 | int status = 0; | |
56 | ZZ_mat<mpz_t> A; | |
57 | status |= read_file(A, TESTDATADIR "tests/lattices/example_list_cvp_in_lattice"); | |
58 | ||
59 | status |= lll_reduction(A); | |
60 | if (status != RED_SUCCESS) | |
61 | { | |
62 | cerr << "LLL reduction failed: " << get_red_status_str(status) << endl; | |
63 | return status; | |
64 | } | |
65 | ||
66 | // Search for up to 999999 vectors, up to radius 32.5 around the origin | |
67 | // the right answer is 196561 | |
68 | FP_NR<FT> rad = 32.5; | |
69 | FP_NR<FT> half_rad = 16.5; | |
70 | const unsigned int right_answer = 196561; | |
71 | ||
72 | // Tests with two targets: 0, and something very close to 0. | |
73 | ||
74 | // HOLE: Not sure how to set that up | |
75 | size_t d = A.get_rows(); | |
76 | if (d != 24) | |
77 | { | |
78 | cerr << "Expected a lattice of dimension 24, got : " << d << endl; | |
79 | return 1; | |
80 | } | |
81 | ||
82 | ZZ_mat<mpz_t> empty_mat; | |
83 | MatGSO<Z_NR<mpz_t>, FP_NR<FT>> gso(A, empty_mat, empty_mat, GSO_INT_GRAM); | |
84 | ||
85 | { | |
86 | gso.update_gso(); | |
87 | FastEvaluator<FP_NR<FT>> evaluator(999999); | |
88 | Enumeration<Z_NR<mpz_t>, FP_NR<FT>> enum_obj(gso, evaluator); | |
89 | ||
90 | std::vector<FP_NR<FT>> target(d, 0.0); | |
91 | enum_obj.enumerate(0, d, rad, 0, target); | |
92 | if (evaluator.size() != right_answer) | |
93 | { | |
94 | cerr << "list CVP failed (center at 0), expected 196561 solutions, got : " << evaluator.size() | |
95 | << endl; | |
96 | return 1; | |
97 | } | |
98 | // cerr << "list CVP (at 0) PASSED : " << evaluator.size() << endl; | |
99 | } | |
100 | ||
101 | { | |
102 | gso.update_gso(); | |
103 | FastEvaluator<FP_NR<FT>> evaluator(999999); | |
104 | Enumeration<Z_NR<mpz_t>, FP_NR<FT>> enum_obj(gso, evaluator); | |
105 | ||
106 | std::vector<FP_NR<FT>> target(d, 0.0001); | |
107 | enum_obj.enumerate(0, d, rad, 0, target); | |
108 | if (evaluator.size() != right_answer) | |
109 | { | |
110 | cerr << "list CVP failed (center near 0), expected 196561 solutions, got : " | |
111 | << evaluator.size() << endl; | |
112 | return 1; | |
113 | } | |
114 | // cerr << "list CVP (near 0) PASSED : " << evaluator.size() << endl; | |
115 | } | |
116 | ||
117 | for (size_t rep = 0; rep < 24; ++rep) | |
118 | { | |
119 | FastEvaluator<FP_NR<FT>> evaluator(999999); | |
120 | Enumeration<Z_NR<mpz_t>, FP_NR<FT>> enum_obj(gso, evaluator); | |
121 | ||
122 | std::vector<FP_NR<FT>> can_target(d, 0.0); | |
123 | ||
124 | // Generate a point in the half lattice | |
125 | for (size_t i = 0; i < d; ++i) | |
126 | { | |
127 | size_t c = (i == rep || rand() % 2); // make sure at least one of them is non-zero | |
128 | // std::cerr << c; | |
129 | if (!c) | |
130 | continue; | |
131 | for (size_t j = 0; j < d; ++j) | |
132 | { | |
133 | can_target[j] += 0.5 * A[i][j].get_d(); | |
134 | } | |
135 | } | |
136 | ||
137 | std::vector<FP_NR<FT>> target(d, 0.0); | |
138 | // Convert it to GSO basis | |
139 | for (size_t i = 0; i < d; ++i) | |
140 | { | |
141 | for (size_t j = 0; j < d; ++j) | |
142 | { | |
143 | target[i] += A[i][j].get_d() * can_target[j]; | |
144 | } | |
145 | ||
146 | for (size_t j = 0; j < i; ++j) | |
147 | { | |
148 | FP_NR<FT> mu_ij; | |
149 | gso.get_mu(mu_ij, i, j); | |
150 | target[i] -= target[j] * mu_ij; | |
151 | } | |
152 | } | |
153 | for (size_t i = 0; i < d; ++i) | |
154 | { | |
155 | FP_NR<FT> r_ii; | |
156 | gso.get_r(r_ii, i, i); | |
157 | target[i] /= r_ii; | |
158 | } | |
159 | ||
160 | enum_obj.enumerate(0, d, half_rad, 0, target); | |
161 | ||
162 | if (evaluator.size() != 2 && evaluator.size() != 48) | |
163 | { | |
164 | cerr << "list CVP failed (halfway), expected 2 or 48 solutions, got : " << evaluator.size() | |
165 | << endl; | |
166 | return 1; | |
167 | } | |
168 | // cerr << "list CVP failed (halfway) PASSED : " << evaluator.size() << endl; | |
169 | } | |
170 | ||
171 | return 0; | |
44 | 172 | } |
45 | 173 | |
46 | 174 | bool callback_firstf(size_t n, enumf *new_sol_coord, void *ctx) |
91 | 219 | int status = 0; |
92 | 220 | status |= test_enum<double>(30); |
93 | 221 | status |= test_callback_enum<double>(40); |
94 | ||
222 | status |= test_list_cvp<double>(); | |
95 | 223 | if (status == 0) |
96 | 224 | { |
97 | 225 | std::cerr << "All tests passed." << std::endl; |
31 | 31 | DSVP_REDUCE |
32 | 32 | }; |
33 | 33 | |
34 | double inline norm(const vector<Z_NR<mpz_t>> &v) | |
35 | { | |
36 | Z_NR<mpz_t> norm, tmp; | |
37 | for (size_t i = 0; i < v.size(); i++) | |
38 | { | |
39 | tmp.mul(v[i], v[i]); | |
40 | norm.add(norm, tmp); | |
41 | } | |
42 | return sqrt(norm.get_d()); | |
43 | } | |
44 | ||
34 | 45 | /** |
35 | 46 | @brief Test if SVP function returns vector with right norm. |
36 | 47 | |
44 | 55 | vector<Z_NR<mpz_t>> sol_coord; // In the LLL-reduced basis |
45 | 56 | vector<Z_NR<mpz_t>> sol_coord2; // In the initial basis |
46 | 57 | vector<Z_NR<mpz_t>> solution; |
47 | ZZ_mat<mpz_t> u; | |
58 | ZZ_mat<mpz_t> u(A.get_rows(), A.get_rows()); | |
48 | 59 | |
49 | 60 | int status = |
50 | 61 | lll_reduction(A, u, LLL_DEF_DELTA, LLL_DEF_ETA, LM_WRAPPER, FT_DEFAULT, 0, LLL_DEFAULT); |
249 | 260 | } |
250 | 261 | |
251 | 262 | return 0; |
263 | } | |
264 | ||
265 | /** | |
266 | @brief test that proved is no worse than fast. | |
267 | ||
268 | @param d large dimension of initial lattice | |
269 | @param d2 enumeration dimension | |
270 | ||
271 | */ | |
272 | ||
273 | int test_svp_proved_vs_fast(size_t d, size_t d2) | |
274 | { | |
275 | ZZ_mat<mpz_t> A(d, d); | |
276 | A.gen_qary_withq(d / 2, 65537); | |
277 | ||
278 | int r = lll_reduction(A); | |
279 | ZZ_mat<mpz_t> B(d2, d); // so that LLL doesn't just solve it | |
280 | vector<Z_NR<mpz_t>> sol_coord_proved, sol_coord_fast; | |
281 | vector<Z_NR<mpz_t>> solution_proved, solution_fast; | |
282 | ||
283 | for (size_t i = 0; i < d2; i++) | |
284 | { | |
285 | for (int j = 0; j < A.get_cols(); j++) | |
286 | B[i][j] = A[i][j]; | |
287 | } | |
288 | ||
289 | r |= shortest_vector(B, sol_coord_proved, SVPM_PROVED); | |
290 | r |= shortest_vector(B, sol_coord_fast, SVPM_FAST); | |
291 | ||
292 | vector_matrix_product(solution_proved, sol_coord_proved, B); | |
293 | vector_matrix_product(solution_fast, sol_coord_fast, B); | |
294 | r |= (norm(solution_fast) < norm(solution_proved)); | |
295 | return r; | |
252 | 296 | } |
253 | 297 | |
254 | 298 | int test_rank_defect() |
320 | 364 | int main() |
321 | 365 | { |
322 | 366 | |
367 | RandGen::init_with_seed(0); | |
368 | ||
323 | 369 | int status = 0; |
324 | 370 | status |= test_filename<mpz_t>(TESTDATADIR "/tests/lattices/example_svp_in", |
325 | 371 | TESTDATADIR "/tests/lattices/example_svp_out"); |
329 | 375 | TESTDATADIR "/tests/lattices/example_dsvp_out", DSVP_REDUCE); |
330 | 376 | |
331 | 377 | status |= test_rank_defect(); |
378 | status |= test_svp_proved_vs_fast(100, 30); | |
332 | 379 | |
333 | 380 | if (status == 0) |
334 | 381 | { |