Codebase list fplll / 3d1c354
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
26 changed file(s) with 432 addition(s) and 166 deletion(s). Raw diff Collapse all Expand all
66 - cron: '0 0 * * 0' # weekly
77
88 env:
9 MAX_ENUM_DIM: 64
10 MAX_PARALLEL_ENUM_DIM: 20
119 JOBS: 2
10 CONFIGURE_OPTS: --enable-recursive-enum --with-max-enum-dim=64 --with-max-parallel-enum-dim=64
1211
1312 jobs:
1413 linux:
1514 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
1722 steps:
23 - name: Echo Configure Options
24 env:
25 CONFIGURE_OPTS: ${{ matrix.configure-options }}
26 run: echo $CONFIGURE_OPTS
1827 - name: Check out
1928 uses: actions/checkout@v2
2029 - name: Install prerequisites
2332 sudo DEBIAN_FRONTEND=noninteractive apt-get install autoconf automake libtool libgmp-dev libmpfr-dev libqd-dev
2433 - name: Configure
2534 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
2937 - name: Compile
3038 run: make -j $JOBS
3139
4755 - name: Configure
4856 run: |
4957 ./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
5259 - name: Compile
5360 run: make -j $JOBS
5461
7373 /tests/test_enum
7474 /tests/test_bkz_gram
7575 /tests/test_svp_gram
76 /tests/test_counter
77 /.cache/
3737 # could be handy for archiving the generated documentation or if some version
3838 # control system is used.
3939
40 PROJECT_NUMBER = 5.4.1
40 PROJECT_NUMBER = 5.4.2
4141
4242 # Using the PROJECT_BRIEF tag one can provide an optional one line description
4343 # for a project that appears at the top of each page and should give viewer a
1616
1717 @unpublished{fplll,
1818 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,
2121 note = {Available at \url{https://github.com/fplll/fplll}},
2222 url = {https://github.com/fplll/fplll}
2323 }
408408
409409 - [json.hpp](fplll/io/json.hpp) is taken from https://github.com/nlohmann/json
410410
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.
412412
413413 # Contributing #
414414
00 # -*- Autoconf -*-
11 # Process this file with autoconf to produce a configure script.
22
3 AC_PREREQ(2.61)
4 AC_INIT(fplll, 5.4.1)
3 AC_PREREQ([2.69])
4 AC_INIT([fplll],[5.4.2])
55 AC_CONFIG_SRCDIR([fplll/fplll.cpp])
66 AM_MAINTAINER_MODE([enable])
7 AC_CANONICAL_TARGET
78
89 # cf http://comments.gmane.org/gmane.comp.sysutils.autoconf.general/15737
910
1819 AM_INIT_AUTOMAKE([foreign subdir-objects])
1920 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
2021
21 AC_CONFIG_HEADER(config.h)
22 AC_CONFIG_HEADERS([config.h])
2223
2324 DEFAULT_CXXFLAGS="-O3 -Wall"
2425
3940 # current, and set both revision and age to zero.
4041
4142 FPLLL_LT_CURRENT=7
42 FPLLL_LT_REVISION=0
43 FPLLL_LT_REVISION=1
4344 FPLLL_LT_AGE=0
4445
4546 AC_SUBST(FPLLL_LT_CURRENT)
4950 AC_PROG_INSTALL
5051
5152 # Checks for programs.
52 AC_LANG_CPLUSPLUS
53 AC_LANG([C++])
5354 AC_PROG_CXX
5455 AC_PROG_CC
5556 AC_PROG_MAKE_SET
138139 # the AC_SEARCH_LIBS macro works.
139140 AC_SUBST(LIBQD_LIBS)
140141
141 # Checks for header files.
142 AC_HEADER_STDC
143142 AC_CHECK_HEADERS([limits.h cstdio iostream string limits vector])
144143
145144 # Checks for typedefs, structures, and compiler characteristics.
175174 AC_DEFINE([FPLLL_WITH_RECURSIVE_ENUM], [1], [recursive enumeration enabled])])
176175
177176
178 max_parallel_enum_dim=80
177 max_parallel_enum_dim=120
179178 AC_ARG_WITH(max-parallel-enum-dim,
180179 AS_HELP_STRING([--with-max-parallel-enum-dim@<:@=DIM@:>@],
181180 [Maximum supported parallel enumeration dimension (max=160, default=120, disable=0).]),
123123
124124 install-data-hook:
125125 echo "#include <fplll/fplll.h>" > "$(builddir)/fplll.h.root"
126 echo "using namespace fplll;" >> "$(builddir)/fplll.h.root"
127126 $(INSTALL) -m 644 "$(builddir)/fplll.h.root" "${DESTDIR}$(includedir)/fplll.h"
128127 rm -f "$(builddir)/fplll.h.root"
129128
8080 {
8181 json js;
8282 {
83 std::ifstream fs(filename);
83 std::ifstream fs(strategy_full_path(filename));
8484 if (fs.fail())
8585 throw std::runtime_error("Cannot open strategies file.");
8686 fs >> js;
7676 << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[kk]);
7777 enumerate_recursive(opts<kk - 1, kk_start, dualenum, findsubsols, enable_reset>());
7878
79 if (partdist[kk] != 0.0)
79 if (!is_svp || partdist[kk] != 0.0)
8080 {
8181 x[kk] += dx[kk];
8282 ddx[kk] = -ddx[kk];
8383 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];
96107 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;
142115 }
143116 }
144117 }
7171 protected:
7272 /* configuration */
7373 bool dual;
74 bool is_svp;
74 bool is_svp; // only for SVP: exploit symmetry in enumeration to half search space
7575 bool resetflag;
7676
7777 /* enumeration input */
155155 if (k >= k_end)
156156 return false;
157157 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 }
159169 }
160170 return true;
161171 }
282282 vector<Z_NR<mpz_t>> new_sol, coord;
283283
284284 gen_zero_vect(new_sol, n);
285 gen_zero_vect(coord, n);
285 gen_zero_vect(coord, gso.get_rows_of_b());
286286 new_sol_dist = 0;
287287
288288 // Computes the distance between x and zero
319319 vector<Z_NR<mpz_t>> new_sol, coord;
320320
321321 gen_zero_vect(new_sol, n);
322 gen_zero_vect(coord, n);
322 gen_zero_vect(coord, gso.get_rows_of_b());
323323 new_sol_dist = 0;
324324
325325 // Computes the distance between x[[offset,d)] and zero
212212 ZT tmp;
213213 sqnorm = 0;
214214 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++)
216216 {
217217 tmp.mul(tmpvec[j], tmpvec[j]);
218218 sqnorm.add(sqnorm, tmp);
7070 * (in this case both must have the same number of rows).
7171 * If u is initially the identity matrix, multiplying transform by the
7272 * 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.
7375 * @param u_inv_t
7476 * Inverse transform (should be empty, which disables the computation, or
7577 * initialized with identity matrix). It works only if u is not empty.
201203 * (lower triangular matrix)
202204 * mu(i, j) = r(i, j) / ||b*_j||^2.
203205 */
204 const Matrix<FT> &get_mu_matrix() { return mu; }
206 const Matrix<FT> &get_mu_matrix() const { return mu; }
205207
206208 /**
207209 * Returns the r matrix
208210 * Coefficients of the Gram Schmidt Orthogonalization
209211 * (lower triangular matrix)
210212 */
211 const Matrix<FT> &get_r_matrix() { return r; }
213 const Matrix<FT> &get_r_matrix() const { return r; }
212214
213215 /**
214216 * Returns the g matrix (Z_NR version of r)
215217 * Coefficients of the Gram Schmidt Orthogonalization
216218 * (lower triangular matrix)
217219 */
218 const Matrix<ZT> &get_g_matrix()
220 const Matrix<ZT> &get_g_matrix() const
219221 {
220222 if (gptr == nullptr)
221223 {
233235 * The returned value is a reference to the coefficient of the internal
234236 * matrix, which may change if the matrix is modified.
235237 */
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;
238240
239241 /**
240242 * Returns f = (b_i, b*_j) / ||b*_j||^2.
261263 * The returned value is a reference to the coefficient of the internal
262264 * matrix, which may change if the matrix is modified
263265 */
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;
266268
267269 /**
268270 * Returns f = (b_i, b*_j).
645647 }
646648
647649 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
649651 {
650652 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < i && j < gso_valid_cols[i] &&
651653 !in_row_op_range(i));
656658 return mu(i, j);
657659 }
658660
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
660663 {
661664 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < i && j < gso_valid_cols[i] &&
662665 !in_row_op_range(i));
674677 }
675678
676679 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
678681 {
679682 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < gso_valid_cols[i] &&
680683 !in_row_op_range(i));
685688 return r(i, j);
686689 }
687690
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
689693 {
690694 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < gso_valid_cols[i] &&
691695 !in_row_op_range(i));
2626 * *
2727 \*********************************************************************************/
2828
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
3331
3432 #include <cstdint>
3533 #include <memory>
4341 #include <future>
4442 #include <atomic>
4543
46
47 #include <fplll/defs.h>
48 FPLLL_BEGIN_NAMESPACE
49
5044 /*************************** example usage ***************************************\
5145 grep "^//test.cpp" thread_pool.hpp -A33 > test.cpp
5246 g++ -std=c++11 -o test test.cpp -pthread -lpthread
204198
205199 inline void thread_pool::push(const std::function<void()>& f)
206200 {
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 }
209205 _condition.notify_one();
210206 }
211207
212208 inline void thread_pool::push(std::function<void()>&& f)
213209 {
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 }
216214 _condition.notify_one();
217215 }
218216
231229 {
232230 if (threads < 1 || threads > int(_threads.size())+1)
233231 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();
237240 }
238241
239242 inline void thread_pool::run(const std::function<void(int)>& f, int threads)
240243 {
241244 if (threads < 1 || threads > int(_threads.size())+1)
242245 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();
246254 }
247255
248256 inline void thread_pool::run(const std::function<void(int,int)>& f, int threads)
249257 {
250258 if (threads < 1 || threads > int(_threads.size())+1)
251259 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();
255268 }
256269
257270 inline void thread_pool::resize(std::size_t nrthreads)
337350 if (++_i >= _count)
338351 {
339352 _i = 0;
353 lock.unlock();
340354 _condition.notify_all();
341355 }
342356 else
347361
348362 } // namespace thread_pool
349363
350 FPLLL_END_NAMESPACE
351
352 #endif // FPLLL_THREAD_POOL_HPP
364 #endif // THREAD_POOL_HPP
3535 * needed).
3636 */
3737 LLLReduction(MatGSOInterface<ZT, FT> &m, double delta, double eta, int flags);
38
3938 #ifdef FPLLL_WITH_LONG_DOUBLE
4039 ~LLLReduction() { LDConvHelper::free(); }
4140 #endif
42
4341 /**
4442 @brief LLL reduction.
4543
247247 ZZ_mat<mpz_t> u;
248248 bool with_coord = strchr(format, 'c') != NULL;
249249 bool with_coord_std = strchr(format, 's') != NULL;
250 int flags = SVP_DEFAULT | (o.verbose ? SVP_VERBOSE : 0);
251250 int flagsLLL = LLL_DEFAULT | (o.verbose ? LLL_VERBOSE : 0);
251 int flags;
252252 int status;
253253
254254 if (!o.no_lll)
269269 }
270270
271271 if (target.empty())
272 {
273 flags = SVP_DEFAULT | (o.verbose ? SVP_VERBOSE : 0);
272274 status = shortest_vector(b, sol_coord, SVPM_PROVED, flags);
275 }
273276 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 }
275281
276282 if (status != RED_SUCCESS)
277283 {
2828 */
2929 inline FP_NR<F>();
3030 inline FP_NR<F>(const FP_NR<F> &f);
31 inline ~FP_NR<F>();
31 inline ~FP_NR();
3232 inline FP_NR<F>(const double d) : FP_NR<F>() { *this = d; };
3333 inline FP_NR<F>(const char *s) : FP_NR<F>() { *this = s; };
3434
2323 /**
2424 * Constructors.
2525 */
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();
3030
3131 /** get data */
3232
235235 */
236236 #ifdef FPLLL_WITH_LONG_DOUBLE
237237
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
238246 class LDConvHelper
239247 {
240248 public:
242250 static long double mpz_get_ld(const mpz_t op)
243251 {
244252 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
247255 }
248256
249257 static void free() { free_temp(); }
255263 static long double mpz_get_ld_2exp(long *exp, const mpz_t op)
256264 {
257265 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
260268 }
261269
262270 /** Sets the value of rop from op. */
263271 static void mpz_set_ld(mpz_t rop, long double op)
264272 {
265273 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);
268276 }
269277
270278 private:
271279 static inline void init_temp()
272280 {
273 if (!temp_initialized)
281 if (!temp_mpfr_initialized)
274282 {
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;
277285 }
278286 }
279287
280288 static inline void free_temp()
281289 {
282 if (temp_initialized)
290 if (temp_mpfr_initialized)
283291 {
284 mpfr_clear(temp);
285 temp_initialized = false;
292 mpfr_clear(temp_mpfr);
293 temp_mpfr_initialized = false;
286294 }
287295 }
288
289 // These static members are initialized in util.cpp
290 static mpfr_t temp;
291 static bool temp_initialized;
292296 };
293297
294298 #endif
2626 MINPREC_L2
2727 };
2828
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 */
3133 #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};
3436 #endif
3537
3638 /* State of the random generator (declared in nr.h, must be defined in exactly
4040 void vector_matrix_product(vector<ZT> &result, const vector<ZT> &x, const Matrix<ZT> &m)
4141 {
4242 int nrows = m.get_rows(), ncols = m.get_cols();
43 FPLLL_CHECK(x.size() == (unsigned int)nrows, "vector_matrix_product(): dimensions do not match!");
4344 gen_zero_vect(result, ncols);
4445 for (int i = 0; i < nrows; i++)
4546 for (int j = 0; j < ncols; j++)
5253 void vector_matrix_product(NumVect<ZT> &result, const NumVect<ZT> &x, const Matrix<ZT> &m)
5354 {
5455 int nrows = m.get_rows(), ncols = m.get_cols();
56 FPLLL_CHECK(x.size() == nrows, "vector_matrix_product(): dimensions do not match!");
5557 result.gen_zero(ncols);
5658 for (int i = 0; i < nrows; i++)
5759 for (int j = 0; j < ncols; j++)
2424 /* The matrix b must not be modified before calling lll().
2525 lll() must be called only once. */
2626
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 */
2749 class Wrapper
2850 {
2951 public:
1515 # The second argument, if specified, indicates whether you insist on an
1616 # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
1717 # -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.
1919 #
2020 # The third argument, if specified 'mandatory' or if left unspecified,
2121 # indicates that baseline support for the specified C++ standard is
3434 # Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
3535 # Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
3636 # Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
37 # Copyright (c) 2020 Jason Merrill <jason@redhat.com>
3738 #
3839 # Copying and distribution of this file, with or without modification, are
3940 # permitted in any medium without royalty provided the copyright notice
4041 # and this notice are preserved. This file is offered as-is, without any
4142 # warranty.
4243
43 #serial 11
44 #serial 12
4445
4546 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
4647 dnl (serial version number 13).
6061 [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
6162 AC_LANG_PUSH([C++])dnl
6263 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])
6374
6475 m4_if([$2], [noext], [], [dnl
6576 if test x$ac_success = xno; then
1313 # flags that are needed. (The user can also force certain compiler
1414 # flags/libs to be tested by setting these environment variables.)
1515 #
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.)
1920 #
2021 # NOTE: You are assumed to not only compile your program with these flags,
2122 # but also to link with them as well. For example, you might link with
2223 # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
24 # $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
2325 #
2426 # If you are only building threaded programs, you may wish to use these
2527 # variables in your default LIBS, CFLAGS, and CC:
2628 #
2729 # LIBS="$PTHREAD_LIBS $LIBS"
2830 # CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
31 # CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
2932 # CC="$PTHREAD_CC"
33 # CXX="$PTHREAD_CXX"
3034 #
3135 # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
3236 # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
8286 # modified version of the Autoconf Macro, you may extend this special
8387 # exception to the GPL to apply to your modified version as well.
8488
85 #serial 27
89 #serial 30
8690
8791 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
8892 AC_DEFUN([AX_PTHREAD], [
89 AC_REQUIRE([AC_CANONICAL_HOST])
93 AC_REQUIRE([AC_CANONICAL_TARGET])
9094 AC_REQUIRE([AC_PROG_CC])
9195 AC_REQUIRE([AC_PROG_SED])
9296 AC_LANG_PUSH([C])
104108 ax_pthread_save_CFLAGS="$CFLAGS"
105109 ax_pthread_save_LIBS="$LIBS"
106110 AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
111 AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
107112 CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
108113 LIBS="$PTHREAD_LIBS $LIBS"
109114 AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
152157 # --thread-safe: KAI C++
153158 # pthread-config: use pthread-config program (for GNU Pth library)
154159
155 case $host_os in
160 case $target_os in
156161
157162 freebsd*)
158163
242247 # definitions is, on some systems, a strong hint that pthreads support is
243248 # correctly enabled
244249
245 case $host_os in
250 case $target_os in
246251 darwin* | hpux* | linux* | osf* | solaris*)
247252 ax_pthread_check_macro="_REENTRANT"
248253 ;;
385390 # step
386391 ax_pthread_save_ac_link="$ac_link"
387392 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"`
389394 ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
390395 ax_pthread_save_CFLAGS="$CFLAGS"
391396 for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
444449 AC_CACHE_CHECK([whether more special flags are required for pthreads],
445450 [ax_cv_PTHREAD_SPECIAL_FLAGS],
446451 [ax_cv_PTHREAD_SPECIAL_FLAGS=no
447 case $host_os in
452 case $target_os in
448453 solaris*)
449454 ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
450455 ;;
474479
475480 # More AIX lossage: compile with *_r variant
476481 if test "x$GCC" != "xyes"; then
477 case $host_os in
482 case $target_os in
478483 aix*)
479484 AS_CASE(["x/$CC"],
480485 [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
481486 [#handle absolute path differently from PATH based program lookup
482487 AS_CASE(["x$CC"],
483488 [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 ])
486499 ;;
487500 esac
488501 fi
489502 fi
490503
491504 test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
505 test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
492506
493507 AC_SUBST([PTHREAD_LIBS])
494508 AC_SUBST([PTHREAD_CFLAGS])
495509 AC_SUBST([PTHREAD_CC])
510 AC_SUBST([PTHREAD_CXX])
496511
497512 # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
498513 if test "x$ax_pthread_ok" = "xyes"; then
3030 lattices/example_cvp_out3 \
3131 lattices/example_cvp_out4 \
3232 lattices/example_cvp_out5 \
33 lattices/example_list_cvp_in_lattice \
3334 lattices/grammatrix_dimension4 \
3435 lattices/grammatrix_dimension4_out \
3536 lattices/grammatrix_dimension7 \
36 lattices/grammatrix_dimension7_out
37 lattices/grammatrix_dimension7_out
3738
3839 # include TOPBUILDIR for fplll_config.h
3940 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]]
1414
1515 #include <cstring>
1616 #include <fplll/fplll.h>
17 #include <test_utils.h>
1718
1819 using namespace fplll;
1920
4142 {
4243 return 0;
4344 }
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;
44172 }
45173
46174 bool callback_firstf(size_t n, enumf *new_sol_coord, void *ctx)
91219 int status = 0;
92220 status |= test_enum<double>(30);
93221 status |= test_callback_enum<double>(40);
94
222 status |= test_list_cvp<double>();
95223 if (status == 0)
96224 {
97225 std::cerr << "All tests passed." << std::endl;
3131 DSVP_REDUCE
3232 };
3333
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
3445 /**
3546 @brief Test if SVP function returns vector with right norm.
3647
4455 vector<Z_NR<mpz_t>> sol_coord; // In the LLL-reduced basis
4556 vector<Z_NR<mpz_t>> sol_coord2; // In the initial basis
4657 vector<Z_NR<mpz_t>> solution;
47 ZZ_mat<mpz_t> u;
58 ZZ_mat<mpz_t> u(A.get_rows(), A.get_rows());
4859
4960 int status =
5061 lll_reduction(A, u, LLL_DEF_DELTA, LLL_DEF_ETA, LM_WRAPPER, FT_DEFAULT, 0, LLL_DEFAULT);
249260 }
250261
251262 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;
252296 }
253297
254298 int test_rank_defect()
320364 int main()
321365 {
322366
367 RandGen::init_with_seed(0);
368
323369 int status = 0;
324370 status |= test_filename<mpz_t>(TESTDATADIR "/tests/lattices/example_svp_in",
325371 TESTDATADIR "/tests/lattices/example_svp_out");
329375 TESTDATADIR "/tests/lattices/example_dsvp_out", DSVP_REDUCE);
330376
331377 status |= test_rank_defect();
378 status |= test_svp_proved_vs_fast(100, 30);
332379
333380 if (status == 0)
334381 {