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) &lt;= 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 &lt;= i &lt; n_known_rows and
180    * 0 &lt;= j &lt;= 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 &lt;= i &lt; n_known_rows and
191    * 0 &lt;= j &lt;= 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) &lt; 2^expo for all j &lt; n_columns.
277    * It is assumed that mu(i, j) is valid for all j &lt; 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| &lt;= 1 and |x| &lt;= 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| &lt;= 1 and |x| &lt;= 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 &lt;= i &lt; n_known_rows (&lt;= d) and
547    * 0 &lt;= j &lt; 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 &lt;= i &lt; n_known_rows (&lt;= d) and
561    * 0 &lt;= j &lt; gso_valid_cols[i] (&lt;= 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