1 | /*--------------------------------------------------------------------------- |
---|
2 | / Integral LLL Algorithm | |
---|
3 | / | |
---|
4 | / Implemented by | |
---|
5 | / Alberto Vigneron-Tenorio and Alfredo Sánchez-Navarro | |
---|
6 | / alberto.vigneron@uca.es, alfredo.sanchez@uca.es | |
---|
7 | / E.U.E.Empresariales de Jerez. | |
---|
8 | / Universidad de Cádiz | |
---|
9 | / Porvera 54. | |
---|
10 | / Jerez de la Frontera (Cádiz, Spain) | |
---|
11 | / | |
---|
12 | / | |
---|
13 | / This application computes the LLL-reduced basis of a Z-lattice using | |
---|
14 | / the algorithm 2.6.7 appeared in: | |
---|
15 | / Cohen, H. A course in computational algebraic number theory. | |
---|
16 | / GTM 138, Springer 1996. | |
---|
17 | / | |
---|
18 | / The Input is a file with the structure: | |
---|
19 | / Number of vectors, Number of coordinates | |
---|
20 | / b11 b12 b13 ... b1C | |
---|
21 | / b21 b22 b23 ... b2C | |
---|
22 | / ... | |
---|
23 | / bF1 bF2 bF3 ... bFC | |
---|
24 | / | |
---|
25 | / All these inputs are integer numbers. | |
---|
26 | / | |
---|
27 | / The Output is a LLL-reduced basis of the Z-lattice generated by | |
---|
28 | / (b11,b12,...,b1C),...,(bF1,...,bFC) | |
---|
29 | / | |
---|
30 | / All these outputs are integer numbers. | |
---|
31 | ---------------------------------------------------------------------------*/ |
---|
32 | |
---|
33 | |
---|
34 | /*--------------------------------------------------------------------------- |
---|
35 | | EXAMPLE: | |
---|
36 | | | |
---|
37 | | Let prf be the file: | |
---|
38 | | 2,3 | |
---|
39 | | 1 -2 4 | |
---|
40 | | 2 1 -7 | |
---|
41 | | then: | |
---|
42 | | | |
---|
43 | | ./LLL_lattice <prf | |
---|
44 | | Output: | |
---|
45 | | 1 -2 4 | |
---|
46 | | 3 -1 -3 | |
---|
47 | | | |
---|
48 | | The output is a LLL-reduced basis of the lattice of ZxZxZ generated by | |
---|
49 | | (1,-2,4),(2,1,-7) | |
---|
50 | | | |
---|
51 | ---------------------------------------------------------------------------*/ |
---|
52 | |
---|
53 | |
---|
54 | #include <stdio.h> |
---|
55 | #include <stdlib.h> |
---|
56 | #include <ctype.h> |
---|
57 | #include <new> |
---|
58 | #include <cstring> |
---|
59 | #include <si_gmp.h> |
---|
60 | |
---|
61 | #define LLL_MAX(a,b) (a > b ? a : b) |
---|
62 | |
---|
63 | /* Global variables */ |
---|
64 | mpz_t * lll_d; |
---|
65 | mpz_t ** lll_lambda; |
---|
66 | mpz_t ** lll_b; |
---|
67 | |
---|
68 | mpz_t **proc_entrada (int *F, int *C); |
---|
69 | void lll_swapi (int k, int kmax, int C); |
---|
70 | void lll_redi (int k, int l, int C); |
---|
71 | void lll_test (int *k, int kma, int C); |
---|
72 | void lll_product (mpz_t * a, mpz_t * f, int n, mpz_t * prod); |
---|
73 | |
---|
74 | int main (void) |
---|
75 | { |
---|
76 | int i, j, k, kmax; |
---|
77 | int F, C; |
---|
78 | mpz_t prod; |
---|
79 | mpz_t u; |
---|
80 | mpz_t auxi1; |
---|
81 | mpz_t auxi2; |
---|
82 | mpz_init (prod); |
---|
83 | mpz_init (u); |
---|
84 | mpz_init (auxi1); |
---|
85 | mpz_init (auxi2); |
---|
86 | |
---|
87 | k = 2; /* Initialize */ |
---|
88 | kmax = 1; /* Initialize */ |
---|
89 | |
---|
90 | lll_b = proc_entrada (&F, &C); |
---|
91 | |
---|
92 | lll_d = new mpz_t[F + 1]; |
---|
93 | lll_lambda = new (mpz_t *)[F + 1]; |
---|
94 | mpz_init (lll_d[0]); |
---|
95 | for (i = 1; i <= F; i++) { |
---|
96 | mpz_init (lll_d[i]); |
---|
97 | lll_lambda[i] = new mpz_t[F + 1]; |
---|
98 | for (j = 1; j <= F; j++) |
---|
99 | mpz_init (lll_lambda[i][j]); |
---|
100 | } |
---|
101 | mpz_set_ui (lll_d[0], 1); /* Initialize */ |
---|
102 | lll_product (lll_b[1], lll_b[1], C, &prod); |
---|
103 | mpz_set (lll_d[1], prod); /* Initialize */ |
---|
104 | |
---|
105 | |
---|
106 | /* Incremental Gram-Schmidt */ |
---|
107 | while (k <= F) |
---|
108 | { |
---|
109 | if (k > kmax) |
---|
110 | { |
---|
111 | kmax = k; |
---|
112 | for (j = 1; j < k + 1; j++) |
---|
113 | { |
---|
114 | lll_product (lll_b[k], lll_b[j], C, &prod); |
---|
115 | mpz_set (u, prod); |
---|
116 | for (i = 1; i < j - 1 + 1; i++) |
---|
117 | { |
---|
118 | mpz_mul (auxi1, lll_d[i], u); |
---|
119 | mpz_mul (auxi2, lll_lambda[k][i], lll_lambda[j][i]); |
---|
120 | mpz_sub (u, auxi1, auxi2); |
---|
121 | mpz_tdiv_q (u, u, lll_d[i - 1]); |
---|
122 | } |
---|
123 | if (j < k) |
---|
124 | { |
---|
125 | mpz_set (lll_lambda[k][j], u); |
---|
126 | } |
---|
127 | else |
---|
128 | { |
---|
129 | mpz_set (lll_d[k], u); |
---|
130 | if (mpz_cmp_ui (lll_d[k], 0) == 0) |
---|
131 | { /* The input is not a basis */ |
---|
132 | fprintf (stderr, "\n INPUT NOT BASIS !!!! \n"); |
---|
133 | exit (1); |
---|
134 | } |
---|
135 | } |
---|
136 | } |
---|
137 | } |
---|
138 | lll_test (&k, kmax, C); |
---|
139 | for (i = k - 2; i > 0; i--) |
---|
140 | lll_redi (k, i, C); |
---|
141 | k = k + 1; |
---|
142 | } |
---|
143 | fprintf (stdout, "list res="); |
---|
144 | for (i = 1; i < F + 1; i++) |
---|
145 | { |
---|
146 | printf ("\nlist("); |
---|
147 | for (j = 1; j < C + 1; j++) |
---|
148 | { |
---|
149 | fprintf (stdout, " "); |
---|
150 | mpz_out_str (stdout, 0, lll_b[i][j]); |
---|
151 | if (j!=C) fprintf (stdout, ","); |
---|
152 | } |
---|
153 | if (i!=F) printf("),\n"); |
---|
154 | else printf(");\n"); |
---|
155 | } |
---|
156 | mpz_clear (auxi1); |
---|
157 | mpz_clear (auxi2); |
---|
158 | mpz_clear (u); |
---|
159 | mpz_clear (prod); |
---|
160 | mpz_clear (lll_d[0]); |
---|
161 | for (i = 1; i <= F; i++) |
---|
162 | { |
---|
163 | mpz_clear (lll_d[i]); |
---|
164 | for (j = 1; j <= F; j++) |
---|
165 | mpz_clear (lll_lambda[i][j]); |
---|
166 | delete[]lll_lambda[i]; |
---|
167 | } |
---|
168 | delete[]lll_lambda; |
---|
169 | delete[]lll_d; |
---|
170 | for (i = 1; i < F + 1; i++) |
---|
171 | { |
---|
172 | for (j = 1; j < C + 1; j++) |
---|
173 | mpz_clear (lll_b[i][j]); |
---|
174 | delete[]lll_b[i]; |
---|
175 | } |
---|
176 | delete[]lll_b; |
---|
177 | return 0; |
---|
178 | } |
---|
179 | |
---|
180 | /*--------------------------------------------------------------------------- |
---|
181 | | proc_entrada {}: | |
---|
182 | | Read the input file. | |
---|
183 | |___________________________________________________________________________|*/ |
---|
184 | |
---|
185 | mpz_t **proc_entrada (int *F, int *C) /* Inputs */ |
---|
186 | { |
---|
187 | int numF, numC; |
---|
188 | int i, j, c; |
---|
189 | mpz_t **base; |
---|
190 | mpz_t valor; |
---|
191 | char *aux, caux; |
---|
192 | int tamano=100; |
---|
193 | |
---|
194 | aux=new char[tamano]; |
---|
195 | fscanf (stdin, "%i, %i\n", &numF, &numC); |
---|
196 | base = new (mpz_t *)[numF+1]; |
---|
197 | for (i = 1; i <= numF; i++) { |
---|
198 | base[i] = new mpz_t[numC+1]; |
---|
199 | for (j = 1; j <= numC; j++) |
---|
200 | { |
---|
201 | do { caux=getc (stdin); } |
---|
202 | while (!feof(stdin) && !(caux=='-' || isdigit(caux))); |
---|
203 | mpz_init (base[i][j]); |
---|
204 | c=0; |
---|
205 | if (!feof(stdin)) |
---|
206 | { |
---|
207 | do |
---|
208 | { |
---|
209 | aux[c++]=caux; |
---|
210 | if (c==tamano) |
---|
211 | { |
---|
212 | char *nuevo=new char[3*tamano/2]; |
---|
213 | memcpy (nuevo, aux, tamano); |
---|
214 | delete[] aux; |
---|
215 | aux=nuevo; |
---|
216 | tamano=3*tamano/2; |
---|
217 | } |
---|
218 | caux=getc(stdin); |
---|
219 | } |
---|
220 | while (!feof(stdin) && caux!=' ' && caux!='\n' && caux!='\t'); |
---|
221 | aux[c]='\0'; |
---|
222 | mpz_set_str (base[i][j], aux, 0); |
---|
223 | } |
---|
224 | else |
---|
225 | { |
---|
226 | fprintf(stderr,"Empty file.\n"); |
---|
227 | mpz_set_ui (base[i][j],0); |
---|
228 | } |
---|
229 | } |
---|
230 | } |
---|
231 | *F = numF; |
---|
232 | *C = numC; |
---|
233 | delete[] aux; |
---|
234 | return (base); |
---|
235 | } |
---|
236 | |
---|
237 | /*--------------------------------------------------------------------------- |
---|
238 | | lll_product {}: | |
---|
239 | | Multiply the integer vectors a and f with n coordinates. | |
---|
240 | |___________________________________________________________________________|*/ |
---|
241 | |
---|
242 | void lll_product (mpz_t * a, mpz_t * f, int n, mpz_t * prod) |
---|
243 | { |
---|
244 | int i; |
---|
245 | mpz_t auxi; |
---|
246 | |
---|
247 | mpz_init (auxi); |
---|
248 | mpz_set_ui (*prod, 0); |
---|
249 | for (i = 1; i < n + 1; i++) |
---|
250 | { |
---|
251 | mpz_mul (auxi, a[i], f[i]); |
---|
252 | mpz_add (*prod, *prod, auxi); |
---|
253 | } |
---|
254 | mpz_clear (auxi); |
---|
255 | } |
---|
256 | |
---|
257 | void lll_test (int *k, int kma, int C) /* Test LLL condition */ |
---|
258 | { |
---|
259 | int i; |
---|
260 | mpz_t auxi1; |
---|
261 | mpz_t auxi2; |
---|
262 | mpz_t auxi3; |
---|
263 | mpz_t auxi4; |
---|
264 | |
---|
265 | mpz_init (auxi1); |
---|
266 | mpz_init (auxi2); |
---|
267 | mpz_init (auxi3); |
---|
268 | |
---|
269 | lll_redi (*k, *k - 1, C); |
---|
270 | mpz_mul (auxi1, lll_d[*k], lll_d[*k - 2]); |
---|
271 | mpz_mul_ui (auxi1, auxi1, 4); |
---|
272 | mpz_mul (auxi2, lll_d[*k - 1], lll_d[*k - 1]); |
---|
273 | mpz_mul_ui (auxi2, auxi2, 3); |
---|
274 | mpz_mul (auxi3, lll_lambda[*k][*k - 1], lll_lambda[*k][*k - 1]); |
---|
275 | mpz_mul_ui (auxi3, auxi3, 4); |
---|
276 | mpz_sub (auxi3, auxi2, auxi3); |
---|
277 | if (mpz_cmp (auxi1, auxi3) < 0) |
---|
278 | { |
---|
279 | lll_swapi (*k, kma, C); |
---|
280 | *k = LLL_MAX (2, *k - 1); |
---|
281 | lll_test (&*k, kma, C); |
---|
282 | } |
---|
283 | |
---|
284 | mpz_clear (auxi1); |
---|
285 | mpz_clear (auxi2); |
---|
286 | mpz_clear (auxi3); |
---|
287 | } |
---|
288 | |
---|
289 | /*--------------------------------------------------------------------------- |
---|
290 | | lll_redi {}: | |
---|
291 | | Make some changes in global variables. | |
---|
292 | |___________________________________________________________________________|*/ |
---|
293 | |
---|
294 | |
---|
295 | void lll_redi (int k, int l, int C) |
---|
296 | { |
---|
297 | int i; |
---|
298 | mpz_t q; |
---|
299 | mpz_t auxi1; |
---|
300 | |
---|
301 | mpz_init (q); |
---|
302 | mpz_init (auxi1); |
---|
303 | |
---|
304 | mpz_mul_ui (auxi1, lll_lambda[k][l], 2); |
---|
305 | mpz_abs (auxi1, auxi1); |
---|
306 | |
---|
307 | if (mpz_cmp (auxi1, lll_d[l]) > 0) |
---|
308 | { |
---|
309 | mpz_mul_ui (auxi1, lll_lambda[k][l], 2); |
---|
310 | mpz_add (auxi1, auxi1, lll_d[l]); |
---|
311 | mpz_mul_ui (q, lll_d[l], 2); |
---|
312 | mpz_fdiv_q (q, auxi1, q); |
---|
313 | for (i = 1; i < C + 1; i++) |
---|
314 | { |
---|
315 | mpz_mul (auxi1, q, lll_b[l][i]); |
---|
316 | mpz_sub (lll_b[k][i], lll_b[k][i], auxi1); |
---|
317 | } |
---|
318 | mpz_mul (auxi1, q, lll_d[l]); |
---|
319 | mpz_sub (lll_lambda[k][l], lll_lambda[k][l], auxi1); |
---|
320 | for (i = 1; i <= l - 1; i++) |
---|
321 | { |
---|
322 | mpz_mul (auxi1, q, lll_lambda[l][i]); |
---|
323 | mpz_sub (lll_lambda[k][i], lll_lambda[k][i], auxi1); |
---|
324 | } |
---|
325 | } |
---|
326 | mpz_clear (q); |
---|
327 | mpz_clear (auxi1); |
---|
328 | } |
---|
329 | |
---|
330 | /*--------------------------------------------------------------------------- |
---|
331 | | lll_swapi {}: | |
---|
332 | | Exchange some global variables | |
---|
333 | |___________________________________________________________________________|*/ |
---|
334 | |
---|
335 | void lll_swapi (int k, int kmax, int C) |
---|
336 | { |
---|
337 | int j; |
---|
338 | mpz_t lamb; |
---|
339 | mpz_t B; |
---|
340 | mpz_t auxi1; |
---|
341 | mpz_t auxi2; |
---|
342 | mpz_t t; |
---|
343 | mpz_t swap; |
---|
344 | |
---|
345 | mpz_init (lamb); |
---|
346 | mpz_init (B); |
---|
347 | mpz_init (auxi1); |
---|
348 | mpz_init (auxi2); |
---|
349 | mpz_init (t); |
---|
350 | mpz_init (swap); |
---|
351 | |
---|
352 | for (j = 1; j < C + 1; j++) |
---|
353 | { |
---|
354 | mpz_set (swap, lll_b[k][j]); |
---|
355 | mpz_set (lll_b[k][j], lll_b[k - 1][j]); |
---|
356 | mpz_set (lll_b[k - 1][j], swap); |
---|
357 | } |
---|
358 | if (k > 2) |
---|
359 | { |
---|
360 | for (j = 1; j <= k - 2; j++) |
---|
361 | { |
---|
362 | mpz_set (swap, lll_lambda[k][j]); |
---|
363 | mpz_set (lll_lambda[k][j], lll_lambda[k - 1][j]); |
---|
364 | mpz_set (lll_lambda[k - 1][j], swap); |
---|
365 | } |
---|
366 | } |
---|
367 | |
---|
368 | mpz_set (lamb, lll_lambda[k][k - 1]); |
---|
369 | mpz_mul (auxi1, lll_d[k - 2], lll_d[k]); |
---|
370 | mpz_mul (auxi2, lamb, lamb); |
---|
371 | mpz_add (B, auxi1, auxi2); |
---|
372 | mpz_tdiv_q (B, B, lll_d[k - 1]); |
---|
373 | for (j = k + 1; j <= kmax; j++) |
---|
374 | { |
---|
375 | mpz_set (t, lll_lambda[j][k]); |
---|
376 | mpz_mul (auxi1, lll_d[k], lll_lambda[j][k - 1]); |
---|
377 | mpz_mul (auxi2, lamb, t); |
---|
378 | mpz_sub (auxi1, auxi1, auxi2); |
---|
379 | mpz_tdiv_q (lll_lambda[j][k], auxi1, lll_d[k - 1]); |
---|
380 | mpz_mul (auxi2, lamb, lll_lambda[j][k]); |
---|
381 | mpz_mul (auxi1, B, t); |
---|
382 | mpz_add (auxi1, auxi1, auxi2); |
---|
383 | mpz_tdiv_q (lll_lambda[j][k - 1], auxi1, lll_d[k]); |
---|
384 | } |
---|
385 | mpz_set (lll_d[k - 1], B); |
---|
386 | |
---|
387 | mpz_clear (auxi1); |
---|
388 | mpz_clear (auxi2); |
---|
389 | mpz_clear (lamb); |
---|
390 | mpz_clear (B); |
---|
391 | mpz_clear (t); |
---|
392 | mpz_clear (swap); |
---|
393 | } |
---|