1 /* Copyright (C) 2005-2008 Damien Stehle.
2 Copyright (C) 2007 David Cade.
3 Copyright (C) 2011 Xavier Pujol.
4 Copyright (C) 2019 Koen de Boer
5
6 This file is part of fplll. fplll is free software: you
7 can redistribute it and/or modify it under the terms of the GNU Lesser
8 General Public License as published by the Free Software Foundation,
9 either version 2.1 of the License, or (at your option) any later version.
10
11 fplll is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with fplll. If not, see <http://www.gnu.org/licenses/>. */
18
19 #ifndef FPLLL_GSOInterface_H
20 #define FPLLL_GSOInterface_H
21
22 #include "nr/matrix.h"
23
24 FPLLL_BEGIN_NAMESPACE
25
26 enum MatGSOInterfaceFlags
27 {
28 GSO_DEFAULT = 0,
29 GSO_INT_GRAM = 1,
30 GSO_ROW_EXPO = 2,
31 GSO_OP_FORCE_LONG = 4
32 };
33
34 /**
35 @brief Use Gaussian Heuristic to compute a bound on the length of the
36 shortest vector
37
38 @param max_dist output
39 @param max_dist_expo exponent of output
40 @param block_size block size
41 @param root_det root determinant of lattice
42 @param gh_factor factor by which to multiple bound
43
44 @return new bound if `gh_factor * GH` is shorter than `max_dist`, otherwise `max_dist` is
45 unchanged.
46 */
47
48 template <class FT>
49 void adjust_radius_to_gh_bound(FT &max_dist, long max_dist_expo, int block_size, const FT &root_det,
50 double gh_factor);
51
52 /**
53 * MatGSOInterface provides an interface for performing elementary operations on a basis
54 * and computing its Gram matrix and its Gram-Schmidt orthogonalization.
55 * The Gram-Schmidt coefficients are computed on demand. The object keeps track
56 * of which coefficients are valid after each row operation.
57 */
58
59 template <class ZT, class FT> class MatGSOInterface
60 {
61 public:
62 /**
63 * Constructor.
64 * The precision of FT must be defined before creating an instance of the
65 * class and must remain the same until the object is destroyed (or no longer
66 * needed).
67 * @param b
68 * The matrix on which row operations are performed. It must not be empty.
69 * @param u
70 * If u is not empty, operations on b are also done on u
71 * (in this case both must have the same number of rows).
72 * If u is initially the identity matrix, multiplying transform by the
73 * initial basis gives the current basis.
74 * @param u_inv_t
75 * Inverse transform (should be empty, which disables the computation, or
76 * initialized with identity matrix). It works only if u is not empty.
77 * @param enable_int_gram
78 * If true, coefficients of the Gram matrix are computed with exact integer
79 * arithmetic (type ZT). Otherwise, they are computed in floating-point
80 * (type FT). Note that when exact arithmetic is used, all coefficients of
81 * the first n_known_rows are continuously updated, whereas in floating-point,
82 * they are computed only on-demand. This option cannot be enabled if
83 * enable_row_expo=true.
84 * @param enable_row_expo
85 * If true, each row of b is normalized by a power of 2 before doing
86 * conversion to floating-point, which hopefully avoids some overflows.
87 * This option cannot be enabled if enable_int_gram=true and works only
88 * with FT=double and FT=long double. It is useless and MUST NOT be used
89 * for FT=dpe or FT=mpfr_t.
90 * @param row_op_force_long
91 * Affects the behaviour of row_addmul(_we).
92 * See the documentation of row_addmul.
93 */
94 virtual ~MatGSOInterface();
95
MatGSOInterface(Matrix<ZT> & arg_u,Matrix<ZT> & arg_uinv_t,int flags)96 MatGSOInterface(Matrix<ZT> &arg_u, Matrix<ZT> &arg_uinv_t, int flags)
97 : enable_int_gram(flags & GSO_INT_GRAM), enable_row_expo(flags & GSO_ROW_EXPO),
98 enable_transform(arg_u.get_rows() > 0), enable_inverse_transform(arg_uinv_t.get_rows() > 0),
99 row_op_force_long(flags & GSO_OP_FORCE_LONG), u(arg_u), u_inv_t(arg_uinv_t),
100 n_known_rows(0), n_source_rows(0), n_known_cols(0), cols_locked(false), alloc_dim(0),
101 gptr(nullptr)
102 {
103 #ifdef DEBUG
104 row_op_first = row_op_last = -1;
105 #endif
106 }
107
108 /**
109 * Number of rows of b (dimension of the lattice).
110 * Can be changed with create_row or remove_last_row.
111 */
112 int d;
113
114 /**
115 * Basis of the lattice
116 */
117 // Matrix<ZT> &b;
118
119 /**
120 * The next five functions make calls
121 * from lll.cpp and bkz.cpp indirect.
122 */
123
124 /**
125 * Returns || sum_i x_i b_i ||^2 on vectorial input (x_i)_i
126 * in the Gram version, it returns x^T G x
127 */
128 virtual ZT &sqnorm_coordinates(ZT &sqnorm, vector<ZT> coordinates) = 0;
129
130 /**
131 * Returns maximum exponent of b. In the gram
132 * version it returns a half times the
133 * maximum exponent of g.
134 */
135 virtual long get_max_exp_of_b() = 0;
136
137 /** Returns true if the ith row
138 * of b is zero. In the gram version
139 * it returns true if g(i,i) is zero.
140 */
141 virtual bool b_row_is_zero(int i) = 0;
142
143 /** Returns number of columns of b. In
144 * the gram version it returns the number
145 * of columns of g.
146 */
147 virtual int get_cols_of_b() = 0;
148
149 /** Returns number of rows of b. In
150 * the gram version it returns the number
151 * of of rows of g. This function is made
152 * to reduce code repetition (dump_mu/dump_r)
153 */
154 virtual int get_rows_of_b() = 0;
155
156 /** Negates the ith row of b. Needed
157 * by dbkz_postprocessing.
158 */
159 virtual void negate_row_of_b(int i) = 0;
160
161 /**
162 * When enable_row_expo=true, row_expo[i] is the smallest non-negative integer
163 * such that b(i, j) <= 2^row_expo[i] for all j. Otherwise this array is empty.
164 */
165 vector<long> row_expo;
166
167 /**
168 * Must be called before a sequence of row_addmul(_we).
169 */
170 inline void row_op_begin(int first, int last);
171
172 /**
173 * Must be called after a sequence of row_addmul(_we). This invalidates the
174 * i-th line of the GSO.
175 */
176 void row_op_end(int first, int last);
177
178 /**
179 * Returns Gram matrix coefficients (0 <= i < n_known_rows and
180 * 0 <= j <= i).
181 * If enable_row_expo=false, returns the dot product (b[i], b[j]).
182 * If enable_row_expo=true, returns
183 * (b[i], b[j]) / 2 ^ (row_expo[i] + row_expo[j]).
184 *
185 * Returns reference to `f`.
186 */
187 virtual FT &get_gram(FT &f, int i, int j) = 0;
188
189 /**
190 * Returns *integer* Gram matrix coefficients (0 <= i < n_known_rows and
191 * 0 <= j <= i).
192 * If (enable_int_gram = true), it returns the i,j-th coordinate of the Gram matrix
193 * else it computes the inner product of b_i and b_j
194 * Returns reference to `z`.
195 */
196
197 virtual ZT &get_int_gram(ZT &z, int i, int j) = 0;
198
199 /**
200 * Returns the mu matrix
201 * Coefficients of the Gram Schmidt Orthogonalization
202 * (lower triangular matrix)
203 * mu(i, j) = r(i, j) / ||b*_j||^2.
204 */
get_mu_matrix()205 const Matrix<FT> &get_mu_matrix() { return mu; }
206
207 /**
208 * Returns the r matrix
209 * Coefficients of the Gram Schmidt Orthogonalization
210 * (lower triangular matrix)
211 */
get_r_matrix()212 const Matrix<FT> &get_r_matrix() { return r; }
213
214 /**
215 * Returns the g matrix (Z_NR version of r)
216 * Coefficients of the Gram Schmidt Orthogonalization
217 * (lower triangular matrix)
218 */
get_g_matrix()219 const Matrix<ZT> &get_g_matrix()
220 {
221 if (gptr == nullptr)
222 {
223 throw std::runtime_error("Error: gptr == nullpointer.");
224 }
225 return *gptr;
226 }
227
228 /**
229 * Returns f = mu(i, j) and expo such that
230 * f * 2^expo = (b_i, b*_j) / ||b*_j||^2.
231 * If enable_row_expo=false, expo is always 0.
232 * If enable_row_expo=true, expo = row_expo[i] - row_expo[j]
233 * It is assumed that mu(i, j) is valid.
234 * The returned value is a reference to the coefficient of the internal
235 * matrix, which may change if the matrix is modified.
236 */
237 inline const FT &get_mu_exp(int i, int j, long &expo);
238 inline const FT &get_mu_exp(int i, int j);
239
240 /**
241 * Returns f = (b_i, b*_j) / ||b*_j||^2.
242 *
243 * Returns reference to `f`.
244 */
245 inline FT &get_mu(FT &f, int i, int j);
246
247 /**
248 * Return maximum bstar_i for all i
249 */
250 ZT get_max_gram();
251
252 /**
253 * Return maximum bstar_i for all i
254 */
255 FT get_max_bstar();
256
257 /**
258 * Returns f = r(i, j) and expo such that (b_i, b*_j) = f * 2^expo.
259 * If enable_row_expo=false, expo is always 0.
260 * If enable_row_expo=true, expo = row_expo[i] + row_expo[j]
261 * If is assumed that r(i, j) is valid.
262 * The returned value is a reference to the coefficient of the internal
263 * matrix, which may change if the matrix is modified
264 */
265 inline const FT &get_r_exp(int i, int j, long &expo);
266 inline const FT &get_r_exp(int i, int j);
267
268 /**
269 * Returns f = (b_i, b*_j).
270 *
271 * Returns reference to `f`.
272 */
273 inline FT &get_r(FT &f, int i, int j);
274
275 /**
276 * Returns expo such that mu(i, j) < 2^expo for all j < n_columns.
277 * It is assumed that mu(i, j) is valid for all j < n_columns.
278 */
279 long get_max_mu_exp(int i, int n_columns);
280
281 /**
282 * Updates r(i, j) and mu(i, j) if needed for all j in [0, last_j].
283 * All coefficients of r and mu above the i-th row in columns
284 * [0, min(last_j, i - 1)] must be valid.
285 * If i=n_known_rows, n_known_rows is increased by one.
286 */
287 bool update_gso_row(int i, int last_j);
288
289 /**
290 * Updates r(i, j) and mu(i, j) if needed for all j.
291 * All coefficients of r and mu above the i-th row in columns
292 * [0, min(last_j, i - 1)] must be valid.
293 * If i=n_known_rows, n_known_rows is increased by one.
294 */
295 inline bool update_gso_row(int i);
296
297 /**
298 * Updates all GSO coefficients (mu and r).
299 */
300 inline bool update_gso();
301
302 /**
303 * Allows row_addmul(_we) for all rows even if the GSO has never been computed.
304 */
305 inline void discover_all_rows();
306
307 /**
308 * Sets the value of r(i, j). During the execution of LLL, some coefficients
309 * are computed by the algorithm. They are set directly to avoid double
310 * computation.
311 */
312 void set_r(int i, int j, FT &f);
313
314 /**
315 * Row old_r becomes row new_r and intermediate rows are shifted.
316 * If new_r < old_r, then old_r must be < n_known_rows.
317 */
318 virtual void move_row(int old_r, int new_r) = 0;
319
320 /**
321 * b[i] := b[i] + x * b[j].
322 * After one or several calls to row_addmul, row_op_end must be called.
323 * Special cases |x| <= 1 and |x| <= LONG_MAX are optimized.
324 * x should be an integer.
325 * If row_op_force_long=true, x is always converted to (2^expo * long) instead
326 * of (2^expo * ZT), which is faster if ZT=mpz_t but might lead to a loss of
327 * precision (in LLL, more Babai iterations are needed).
328 */
329 virtual inline void row_addmul(int i, int j, const FT &x);
330
331 /**
332 * b[i] := b[i] + x * 2^expo_add * b[j].
333 * After one or several calls to row_addmul_we, row_op_end must be called.
334 * Special cases |x| <= 1 and |x| <= LONG_MAX are optimized.
335 * x should be an integer.
336 * If row_op_force_long=true, x is always converted to (2^expo * long) instead
337 * of (2^expo * ZT), which is faster if ZT=mpz_t but might lead to a loss of
338 * precision (in LLL, more Babai iterations are needed).
339 */
340
341 virtual void row_addmul_we(int i, int j, const FT &x, long expo_add) = 0;
342
343 // b[i] += b[j] / b[i] -= b[j] (i > j)
344 virtual void row_add(int i, int j) = 0;
345 virtual void row_sub(int i, int j) = 0;
346
347 /**
348 * Early reduction
349 * Allowed when enable_int_gram=false,
350 * n_known_cols large enough to compute all the g(i,j)
351 */
352 void lock_cols();
353 void unlock_cols();
354
355 /**
356 * Adds a zero row to b (and to u if enableTranform=true). One or several
357 * operations can be performed on this row with row_addmul(_we), then
358 * row_op_end must be called.
359 * Do not use if enable_inverse_transform=true.
360 */
361 inline void create_row();
362 virtual void create_rows(int n_new_rows) = 0;
363
364 /**
365 * Removes the last row of b (and of u if enable_transform=true).
366 * Do not use if enable_inverse_transform=true.
367 */
368 inline void remove_last_row();
369 virtual void remove_last_rows(int n_removed_rows) = 0;
370
371 /**
372 * Executes transformation by creating extra rows,
373 * Calculating new entries, swapping the new rows with previous ones,
374 * And then removing the excess rows
375 */
376 void apply_transform(const Matrix<FT> &transform, int src_base, int target_base);
377
apply_transform(const Matrix<FT> & transform,int src_base)378 void apply_transform(const Matrix<FT> &transform, int src_base)
379 {
380 apply_transform(transform, src_base, src_base);
381 }
382
383 /**
384 * Dump mu matrix to parameter `mu`.
385
386 * When a double pointer is provided the caller must ensure it can hold
387 * block_size^2 entries. When a vector is provided new entries are pushed to
388 * the end. In particular, existing entries are not overwritten or cleared.
389 *
390 * @note No row discovery or update is performed prior to dumping the matrix.
391 */
392
393 inline void dump_mu_d(double *mu, int offset = 0, int block_size = -1);
394 inline void dump_mu_d(vector<double> mu, int offset = 0, int block_size = -1);
395
396 /**
397 * Dump r vector to parameter `r`.
398
399 * When a double pointer is provided the caller must ensure it can hold
400 * block_size entries. When a vector is provided new entries are pushed to the
401 * end. In particular, existing entries are not overwritten or cleared.
402 *
403 * @note No row discovery or update is performed prior to dumping the matrix.
404 */
405
406 inline void dump_r_d(double *r, int offset = 0, int block_size = -1);
407 inline void dump_r_d(vector<double> &r, int offset = 0, int block_size = -1);
408
409 /**
410 @brief Return slope of the curve fitted to the lengths of the vectors from
411 `start_row` to `stop_row`.
412
413 The slope gives an indication of the quality of the basis.
414
415 @param start_row start row (inclusive)
416 @param stop_row stop row (exclusive)
417 @return
418 */
419
420 double get_current_slope(int start_row, int stop_row);
421
422 /**
423 @brief Return (squared) root determinant of the basis.
424
425 @param start_row start row (inclusive)
426 @param end_row stop row (exclusive)
427 */
428
429 FT get_root_det(int start_row, int end_row);
430
431 /**
432 @brief Return log of the (squared) determinant of the basis.
433
434 @param start_row start row (inclusive)
435 @param end_row stop row (exclusive)
436 */
437
438 FT get_log_det(int start_row, int end_row);
439
440 /**
441 @brief Return slide potential of the basis
442
443 @param start_row start row (inclusive)
444 @param end_row stop row (exclusive)
445 @param block_size block size
446 */
447
448 FT get_slide_potential(int start_row, int end_row, int block_size);
449
450 /**
451 * Prints mu,r and g matrix to ostream os.
452 *
453 */
454 inline void print_mu_r_g(ostream &os);
455
456 /** Exact computation of dot products (i.e. with type ZT instead of FT) */
457 const bool enable_int_gram;
458
459 /** Normalization of each row of b by a power of 2. */
460 const bool enable_row_expo;
461
462 /** Computation of the transform matrix. */
463 const bool enable_transform;
464
465 /**
466 * Computation of the inverse transform matrix (transposed).
467 * This works only if enable_transform=true.
468 * This matrix has very large coefficients, computing it is slow.
469 */
470 const bool enable_inverse_transform;
471
472 /**
473 * Changes the behaviour of row_addmul(_we).
474 * See the description of row_addmul.
475 */
476 const bool row_op_force_long;
477
478 protected:
479 /** Allocates matrices and arrays whose size depends on d (all but tmp_col_expo).
480 * When enable_int_gram=false, initializes bf.
481 */
482 virtual void size_increased() = 0;
483
484 /* Increases known rows and invalidates the last
485 * gram row (gf) when enable_int_gram is false.
486 * When enable_int_gram is true, it computes
487 * the new inner products for the last gram
488 * row (g).
489 */
490 virtual void discover_row() = 0;
491
492 // Marks mu(i, j) and r(i, j) as invalid for j >= new_valid_cols
493 void invalidate_gso_row(int i, int new_valid_cols = 0);
494 /* Upates the i-th row of bf. It does not invalidate anything, so the caller
495 * must take into account that it might change row_expo.
496 */
497 virtual void update_bf(int i) = 0;
498 /* Marks g(i, j) for all j <= i (but NOT for j > i) */
499 virtual void invalidate_gram_row(int i) = 0;
500
501 // b[i] <- b[i] + x * b[j] (i > j)
502 virtual void row_addmul_si(int i, int j, long x) = 0;
503 // b[i] <- b[i] + (2^expo * x) * b[j] (i > j)
504
505 // TODO check if these must be scratched here!
506 // virtual void row_addmul_si_2exp(int i, int j, long x, long expo) = 0;
507 // virtual void row_addmul_2exp(int i, int j, const ZT &x, long expo) = 0;
508
509 public:
510 // made public for lll.cpp and bkz.cpp
511 void symmetrize_g();
512
513 // Made public for bkz.cpp (dbkz_postprocessing)
514 // b[i] <-> b[j] (i < j)
515 virtual void row_swap(int i, int j) = 0;
516
517 protected:
518 inline ZT &sym_g(int i, int j);
519
520 /* Floating-point representation of the basis. It is used when
521 enable_int_gram=false. */
522 Matrix<FT> bf;
523
524 Matrix<ZT> &u; // Transform
525 Matrix<ZT> &u_inv_t; // Transposed inverse transform
526
527 // init_row_size[i] = (last non-zero column in the i-th row of b) + 1
528 vector<int> init_row_size;
529
530 // bf[i], g[i], gf[i], mu[i] and r[i] are invalid for i >= n_known_rows
531 int n_known_rows;
532 int n_source_rows; // Known rows before the beginning of early reduction
533 int n_known_cols;
534 bool cols_locked;
535 int alloc_dim;
536
537 /**
538 * Coefficients of the Gram-Schmidt orthogonalization
539 * (lower triangular matrix).
540 *
541 * If enable_row_expo=false,
542 * mu(i, j) = (b_i, b*_j) / ||b*_j||^2.
543 * If enable_row_expo=true,
544 * mu(i, j) = (b_i, b*_j) / ||b*_j||^2 / 2 ^ (row_expo[i] - row_expo[j]).
545 *
546 * mu(i, j) is valid if 0 <= i < n_known_rows (<= d) and
547 * 0 <= j < min(gso_valid_cols[i], i)
548 */
549 Matrix<FT> mu;
550
551 /**
552 * Coefficients of the Gram-Schmidt orthogonalization
553 * (lower triangular matrix).
554 *
555 * If enable_row_expo=false,
556 * r(i, j) = (b_i, b*_j).
557 * If enable_row_expo=true,
558 * r(i, j) = (b_i, b*_j) / 2 ^ (row_expo[i] + row_expo[j]).
559 *
560 * r(i, j) is valid if 0 <= i < n_known_rows (<= d) and
561 * 0 <= j < gso_valid_cols[i] (<= i + 1).
562 */
563 Matrix<FT> r;
564
565 public:
566 /** Replaced the gram matrix by a pointer. In the gso-class
567 * there is also a matrix g, and in the constructor gptr is
568 * defined to be equal to &g. In the ggso-class a gram matrix
569 * is given (arg_g), and gptr is defined as &arg_g.
570 */
571
572 /* Gram matrix (dot products of basis vectors, lower triangular matrix)
573 g(i, j) is valid if 0 <= i < n_known_rows and j <= i */
574 Matrix<ZT> *gptr;
575 // Matrix<ZT> g;
576
577 protected:
578 Matrix<FT> gf;
579
580 /* Number of valid columns of the i-th row of mu and r.
581 Valid only for 0 <= i < n_known_rows */
582 vector<int> gso_valid_cols;
583
584 /* Used by update_gso_row (+ update_gso), get_max_mu_exp and row_addmul_we. */
585 FT ftmp1, ftmp2;
586 /* Used by row_add, row_sub, row_addmul_si_2exp, row_addmul_2exp and
587 indirectly by row_addmul. */
588 ZT ztmp1;
589 /* Used by row_addmul. */
590 ZT ztmp2;
591 /* Used by update_bf. */
592 vector<long> tmp_col_expo;
593
594 #ifdef DEBUG
595 /* Used only in debug mode. */
596 int row_op_first, row_op_last;
in_row_op_range(int i)597 bool in_row_op_range(int i) { return i >= row_op_first && i < row_op_last; }
598 #endif
599 };
600
~MatGSOInterface()601 template <class ZT, class FT> inline MatGSOInterface<ZT, FT>::~MatGSOInterface()
602 {
603 // delete gptr;
604 }
605
symmetrize_g()606 template <class ZT, class FT> inline void MatGSOInterface<ZT, FT>::symmetrize_g()
607 {
608 if (gptr == nullptr)
609 {
610 throw std::runtime_error("Error: gptr is equal to the nullpointer.");
611 }
612 Matrix<ZT> &gr = *gptr;
613 for (int i = 0; i < d; i++)
614 {
615 for (int j = 0; j < d; j++)
616 {
617 gr(i, j) = sym_g(i, j);
618 }
619 }
620 }
621
print_mu_r_g(ostream & os)622 template <class ZT, class FT> inline void MatGSOInterface<ZT, FT>::print_mu_r_g(ostream &os)
623 {
624 os << "mu = " << endl;
625 mu.print(os);
626 os << endl << "r = " << endl;
627 r.print(os);
628 os << endl;
629 if (gptr != nullptr)
630 {
631 os << "g = " << endl;
632 symmetrize_g();
633 gptr->print(os);
634 os << endl << endl;
635 }
636 }
637
sym_g(int i,int j)638 template <class ZT, class FT> inline ZT &MatGSOInterface<ZT, FT>::sym_g(int i, int j)
639 {
640 if (gptr == nullptr)
641 {
642 throw std::runtime_error("Error: gptr is equal to the nullpointer.");
643 }
644 Matrix<ZT> &gr = *gptr;
645 return (i >= j) ? gr(i, j) : gr(j, i);
646 }
647
648 template <class ZT, class FT>
get_mu_exp(int i,int j,long & expo)649 inline const FT &MatGSOInterface<ZT, FT>::get_mu_exp(int i, int j, long &expo)
650 {
651 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < i && j < gso_valid_cols[i] &&
652 !in_row_op_range(i));
653 if (enable_row_expo)
654 expo = row_expo[i] - row_expo[j];
655 else
656 expo = 0;
657 return mu(i, j);
658 }
659
get_mu_exp(int i,int j)660 template <class ZT, class FT> inline const FT &MatGSOInterface<ZT, FT>::get_mu_exp(int i, int j)
661 {
662 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < i && j < gso_valid_cols[i] &&
663 !in_row_op_range(i));
664 return mu(i, j);
665 }
666
get_mu(FT & f,int i,int j)667 template <class ZT, class FT> inline FT &MatGSOInterface<ZT, FT>::get_mu(FT &f, int i, int j)
668 {
669 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < i && j < gso_valid_cols[i] &&
670 !in_row_op_range(i));
671 f = mu(i, j);
672 if (enable_row_expo)
673 f.mul_2si(f, row_expo[i] - row_expo[j]);
674 return f;
675 }
676
677 template <class ZT, class FT>
get_r_exp(int i,int j,long & expo)678 inline const FT &MatGSOInterface<ZT, FT>::get_r_exp(int i, int j, long &expo)
679 {
680 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < gso_valid_cols[i] &&
681 !in_row_op_range(i));
682 if (enable_row_expo)
683 expo = row_expo[i] + row_expo[j];
684 else
685 expo = 0;
686 return r(i, j);
687 }
688
get_r_exp(int i,int j)689 template <class ZT, class FT> inline const FT &MatGSOInterface<ZT, FT>::get_r_exp(int i, int j)
690 {
691 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < gso_valid_cols[i] &&
692 !in_row_op_range(i));
693 return r(i, j);
694 }
695
get_r(FT & f,int i,int j)696 template <class ZT, class FT> inline FT &MatGSOInterface<ZT, FT>::get_r(FT &f, int i, int j)
697 {
698 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && j >= 0 && j < gso_valid_cols[i] &&
699 !in_row_op_range(i));
700 f = r(i, j);
701 if (enable_row_expo)
702 f.mul_2si(f, row_expo[i] + row_expo[j]);
703 return f;
704 }
705
update_gso_row(int i)706 template <class ZT, class FT> inline bool MatGSOInterface<ZT, FT>::update_gso_row(int i)
707 {
708 return update_gso_row(i, i);
709 }
710
set_r(int i,int j,FT & f)711 template <class ZT, class FT> inline void MatGSOInterface<ZT, FT>::set_r(int i, int j, FT &f)
712 {
713 FPLLL_DEBUG_CHECK(i >= 0 && i < n_known_rows && gso_valid_cols[i] >= j && j >= 0 &&
714 j < n_source_rows);
715 r(i, j) = f;
716 if (gso_valid_cols[i] == j)
717 gso_valid_cols[i]++;
718 }
719
720 template <class ZT, class FT>
row_addmul(int i,int j,const FT & x)721 inline void MatGSOInterface<ZT, FT>::row_addmul(int i, int j, const FT &x)
722 {
723 row_addmul_we(i, j, x, 0);
724 }
725
create_row()726 template <class ZT, class FT> inline void MatGSOInterface<ZT, FT>::create_row() { create_rows(1); }
727
remove_last_row()728 template <class ZT, class FT> inline void MatGSOInterface<ZT, FT>::remove_last_row()
729 {
730 remove_last_rows(1);
731 }
732
discover_all_rows()733 template <class ZT, class FT> inline void MatGSOInterface<ZT, FT>::discover_all_rows()
734 {
735 while (n_known_rows < d)
736 discover_row();
737 }
738
update_gso()739 template <class ZT, class FT> inline bool MatGSOInterface<ZT, FT>::update_gso()
740 {
741 for (int i = 0; i < d; i++)
742 {
743 if (!update_gso_row(i))
744 return false;
745 }
746 return true;
747 }
748
749 #ifdef DEBUG
row_op_begin(int first,int last)750 template <class ZT, class FT> inline void MatGSOInterface<ZT, FT>::row_op_begin(int first, int last)
751 {
752 FPLLL_DEBUG_CHECK(row_op_first == -1);
753 row_op_first = first;
754 row_op_last = last;
755 }
756 #else
757 template <class ZT, class FT>
row_op_begin(int,int)758 inline void MatGSOInterface<ZT, FT>::row_op_begin(int /*first*/, int /*last*/)
759 {
760 }
761 #endif
762
763 template <class ZT, class FT>
dump_mu_d(double * mu,int offset,int block_size)764 inline void MatGSOInterface<ZT, FT>::dump_mu_d(double *mu, int offset, int block_size)
765 {
766 FT e;
767 if (block_size <= 0)
768 {
769 block_size = get_rows_of_b();
770 }
771
772 for (int i = 0; i < block_size; ++i)
773 {
774 for (int j = 0; j < block_size; ++j)
775 {
776 get_mu(e, offset + i, offset + j);
777 mu[i * block_size + j] = e.get_d();
778 }
779 }
780 }
781
782 template <class ZT, class FT>
dump_mu_d(vector<double> mu,int offset,int block_size)783 inline void MatGSOInterface<ZT, FT>::dump_mu_d(vector<double> mu, int offset, int block_size)
784 {
785 FT e;
786 if (block_size <= 0)
787 {
788 block_size = get_rows_of_b();
789 }
790
791 mu.reserve(mu.size() + block_size * block_size);
792 for (int i = 0; i < block_size; ++i)
793 {
794 for (int j = 0; j < block_size; ++j)
795 {
796 get_mu(e, offset + i, offset + j);
797 mu.push_back(e.get_d());
798 }
799 }
800 }
801
802 template <class ZT, class FT>
dump_r_d(double * r,int offset,int block_size)803 inline void MatGSOInterface<ZT, FT>::dump_r_d(double *r, int offset, int block_size)
804 {
805 FT e;
806 if (block_size <= 0)
807 {
808 block_size = get_rows_of_b();
809 }
810
811 for (int i = 0; i < block_size; ++i)
812 {
813 get_r(e, offset + i, offset + i);
814 r[i] = e.get_d();
815 }
816 }
817
818 template <class ZT, class FT>
dump_r_d(vector<double> & r,int offset,int block_size)819 inline void MatGSOInterface<ZT, FT>::dump_r_d(vector<double> &r, int offset, int block_size)
820 {
821 FT e;
822 if (block_size <= 0)
823 {
824 block_size = get_rows_of_b();
825 }
826
827 r.reserve(r.size() + block_size * block_size);
828 for (int i = 0; i < block_size; ++i)
829 {
830 get_r(e, offset + i, offset + i);
831 r.push_back(e.get_d());
832 }
833 }
834
835 FPLLL_END_NAMESPACE
836
837 #endif
838