Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

563665 views
1
/***** Main program for the isometry program ISOM *****/
2
/**************************************************************************\
3
@---------------------------------------------------------------------------
4
@---------------------------------------------------------------------------
5
@ FILE: isometry.c
6
@---------------------------------------------------------------------------
7
@---------------------------------------------------------------------------
8
@
9
\**************************************************************************/
10
11
#include"typedef.h"
12
#include "types.h"
13
14
static int normal_option;
15
static int perp_no;
16
static int ***perp;
17
static int perpdim;
18
static int ***perpbase;
19
static int ***perpprod;
20
static int *perpvec;
21
22
#include "isotools.c"
23
#include "bachtools.c"
24
#include "iotools.c"
25
#include "lattools.c"
26
#include "mattools.c"
27
#include "orbtools.c"
28
#include "preproc.c"
29
#include "sorttools.c"
30
#include "perfecttools.c"
31
32
/*
33
@-------------------------------------------------------------------------
34
@ matrix_TYP *isometry(F1, F2, Fanz, SV1, SV2, Erz, Erzanz, options)
35
@ matrix_TYP **F1, **F2, *SV1, *SV2, **Erz;
36
@ int Fanz, Erzanz, *options;
37
@
38
@ The function 'isometry' calculates a matrix X such that
39
@ X * F1[i] *X^{tr} = F2[i] for 1<= i<= Foanz
40
@ returned via a pointer to 'matrix_TYP'.
41
@ If no such matrix exists the functions returns NULL
42
@
43
@ The arguments of isometry are:
44
@ matrix_TYP **F1: a set of n times n matrices,
45
@ the first must be positiv definite
46
@ matrix_TYP **F2: a set of n times n matrices,
47
@ the first must be positiv definite
48
@ int Fanz: the number of the matrices given in 'F1'.
49
@ matrix_TYP *SV1: The rows of the matrix 'SV1' must be the vectors
50
@ x in Z^n with x * F1[0] * x^{tr} <= m, where
51
@ m is the maximal diagonal entry of the Matrix
52
@ F1[0]
53
@ matrix_TYP *SV2: The rows of the matrix 'SV2' must be the vectors
54
@ x in Z^n with x * F2[0] * x^{tr} <= m, where
55
@ m is the maximal diagonal entry of the Matrix
56
@ F.[0]
57
@ int *options: see below.
58
@ matrix_TYP **Erz: if already elements with g^{tr}F1[i]g = F2[i]
59
@ are known, the can be used for calculating
60
@ the isometry.
61
@ The matrices of known elements can be given
62
@ to the function by the pointer 'Erz'.
63
@ int Erzanz: The number of matrices given in 'Erz"
64
@ int *options: see below.
65
@
66
@ options is a pointer to integer (of length 6)
67
@ The possible options are encoded in the following way:
68
@ options[0]: The depth, up to wich scalar product combinations
69
@ shall be calculated. The value should be small.
70
@ options[0] > 0 should be used only, if the automorphismn
71
@ group is expected to be small (with respect to the number
72
@ of shortest vectors).
73
@ options[1]: The n-point stabiliser with respect to different basis
74
@ will be calculated.
75
@ options[2]: If options[2] = 1, additional output is written to the
76
@ file AUTO.tmp
77
@ options[3]: If options[3] = 1, Bacher polynomials are used.
78
@ If options[3] = 2, Bacher polynomial are used up to a deepth
79
@ specified in options[4].
80
@ If options[3] = 3, Bacher polynomials are used, using
81
@ combinations of vectors having the scalar
82
@ product specified in options[5]
83
@ options[3] = 4 is the combination of options[3] = 2 and
84
@ options[3] = 3.
85
@ options[4]: A natural number number or zero (if options[3] = 2 or 4)
86
@ options[5]: An integral number (if options[3] = 3 or 4)
87
@
88
@ It is possible to use NULL for options,
89
@ in this case option is assumed to be [0,0,0,0,0,0]
90
@-------------------------------------------------------------------------
91
*/
92
93
matrix_TYP *isometry(F1, F2, Fanz, SV1, SV2, Erz, Erzanz, options)
94
matrix_TYP **F1, **F2, *SV1, *SV2, **Erz;
95
int Fanz, Erzanz, *options;
96
{
97
FILE *outfile;
98
bachpol *bach;
99
flagstruct flags;
100
scpcomb *comb;
101
invar F, FF;
102
veclist V, norm;
103
fpstruct fp;
104
int dim, max, fail, *vec;
105
int ***G, nG, ngen, **sumveclist, **sumvecbase;
106
int i, j, k, n, *Vvi, *Vvj, **Fvi, *Fvij, **FAi, nV1;
107
matrix_TYP *erg, *erg1;
108
109
extern matrix_TYP *mat_inv();
110
111
normal_option = FALSE;
112
if(SV1->rows != SV2->rows)
113
return(NULL);
114
/* FF.v[i][j] is the transposed of the product of the Gram-matrix FF.A[i]
115
get the flags from the command line */
116
getflags(&flags, options);
117
if(Erzanz > 0)
118
flags.GEN = 1;
119
else flags.GEN = 0;
120
/* F.n is the number of invariant forms */
121
F.n = Fanz;
122
if ((F.A = (int***)malloc(F.n * sizeof(int**))) == 0)
123
exit (2);
124
/* read the invariant forms of the first lattice */
125
F.dim = F1[0]->cols;
126
dim = F.dim;
127
if(F1[0]->cols != F1[0]->rows)
128
{
129
printf("Non-square matrix as input for isometry\n");
130
exit(3);
131
}
132
for(i=1;i<F.n;i++)
133
{
134
if(F1[i]->rows != F.dim || F1[i]->cols != F.dim)
135
{
136
printf("Different dimensions of the forms in isometry\n");
137
exit(3);
138
}
139
}
140
for(i=0;i<F.n;i++)
141
{
142
if((F.A[i] = (int **)malloc(dim *sizeof(int *))) == 0)
143
{
144
printf("realloc of F.A[%d] failed in isometry\n", i);
145
exit(2);
146
}
147
for(j=0;j<dim;j++)
148
{
149
if((F.A[i][j] = (int *)malloc(dim *sizeof(int))) == 0)
150
{
151
printf("realloc of F.A[%d][%d] failed in isometry\n", i, j);
152
exit(2);
153
}
154
for(k=0;k<dim;k++)
155
F.A[i][j][k] = F1[i]->array.SZ[j][k];
156
}
157
}
158
/* get the short vectors of the first lattice */
159
V.dim = dim;
160
V.len = dim + F.n;
161
V.n = SV1->rows;
162
if((V.v = (int **)malloc((V.n+1) *sizeof(int *))) == 0)
163
{
164
printf("realloc of V.v failed in isometry\n");
165
exit(2);
166
}
167
if((V.v[0] = (int *)malloc(V.len *sizeof(int))) == 0)
168
{
169
printf("realloc of V.v[0] failed in isometry\n");
170
exit(2);
171
}
172
for(j=0;j<V.len;j++)
173
V.v[0][j] = 0;
174
for(i=1;i<=V.n;i++)
175
{
176
if((V.v[i] = (int *)malloc(V.len *sizeof(int))) == 0)
177
{
178
printf("realloc of V.v[%d] failed in isometry\n", i);
179
exit(2);
180
}
181
for(j=0;j<=V.dim;j++)
182
V.v[i][j] = SV1->array.SZ[i-1][j];
183
}
184
/* the first nonzero entry of each vector is made positive and the maximal
185
entry in the vectors is determined */
186
max = 1;
187
for (i = 1; i <= V.n; ++i)
188
{
189
Vvi = V.v[i];
190
for (j = 0; j < dim && Vvi[j] == 0; ++j);
191
if (j < dim && Vvi[j] < 0)
192
{
193
for (k = j; k < dim; ++k)
194
Vvi[k] *= -1;
195
}
196
for (k = j; k < dim; ++k)
197
{
198
if (abs(Vvi[k]) > max)
199
max = abs(Vvi[k]);
200
}
201
}
202
if (max > MAXENTRY)
203
/* there is an entry, which is bigger than MAXENTRY, which might cause overflow,
204
since the program doesn't use long integer arithmetic */
205
{
206
fprintf(stderr, "Error: Found entry %d in short vectors of the first lattice.\nTo avoid overflow, the entries should not exceed %d.\n", max, MAXENTRY);
207
exit (3);
208
}
209
/* sort the vectors and delete doublets */
210
sortvecs(&V);
211
/* the norm-vector (i.e. the vector of the norms with respect to the different
212
invariant forms) of each vector must be equal to the norm-vector of one
213
of the vectors from the standard-base */
214
if ((norm.v = (int**)malloc((dim+1) * sizeof(int*))) == 0)
215
exit (2);
216
norm.n = dim;
217
norm.dim = F.n;
218
norm.len = F.n;
219
for (i = 1; i <= norm.n; ++i)
220
{
221
/* norm.v[i] is the norm combination of the (i-1)-th base-vector */
222
if ((norm.v[i] = (int*)malloc(norm.dim * sizeof(int))) == 0)
223
exit (2);
224
for (k = 0; k < norm.dim; ++k)
225
norm.v[i][k] = F.A[k][i-1][i-1];
226
}
227
sortvecs(&norm);
228
/* delete those vectors, which can not be the image of any vector of the
229
standard-base */
230
checkvecs(&V, F, norm);
231
/* F.v[i][j] is the transposed of the product of the Gram-matrix F.A[i] with the
232
transposed of the vector v[j], hence the scalar product of v[j] and v[k] with
233
respect to the Gram-matrix F.A[i] can be computed as standard scalar product
234
of v[j] and F.v[i][k] */
235
if ((F.v = (int***)malloc(F.n * sizeof(int**))) == 0)
236
exit (2);
237
/* the product of the maximal entry in the short vectors with the maximal entry
238
in F.v[i] should not exceed MAXNORM to avoid overflow */
239
max = MAXNORM / max;
240
for (i = 0; i < F.n; ++i)
241
{
242
FAi = F.A[i];
243
if ((F.v[i] = (int**)malloc((V.n+1) * sizeof(int*))) == 0)
244
exit (2);
245
Fvi = F.v[i];
246
for (j = 1; j <= V.n; ++j)
247
{
248
Vvj = V.v[j];
249
if ((Fvi[j] = (int*)malloc(dim * sizeof(int))) == 0)
250
exit (2);
251
Fvij = Fvi[j];
252
for (k = 0; k < dim; ++k)
253
{
254
Fvij[k] = sscp(FAi[k], Vvj, dim);
255
if (abs(Fvij[k]) > max)
256
/* some entry in F.v[i] is too large */
257
{
258
fprintf(stderr, "Error: Found entry %d in F.v.\nTo avoid overflow, the entries should not exceed %d.\n", Fvij[k], max);
259
exit (3);
260
}
261
}
262
}
263
}
264
/* fp.per is the order in which the images of the base vectors are chosen */
265
if ((fp.per = (int*)malloc(dim * sizeof(int))) == 0)
266
exit (2);
267
/* fp.e[i] is the index in V.v of the i-th vector of the standard-base in the
268
new order */
269
if ((fp.e = (int*)malloc(dim * sizeof(int))) == 0)
270
exit (2);
271
/* fp.diag is the diagonal of the fingerprint in the new order */
272
if ((fp.diag = (int*)malloc(dim * sizeof(int))) == 0)
273
exit (2);
274
/* compute the fingerprint */
275
fingerprint(&fp, F, V);
276
if (flags.PRINT == 1)
277
/* if the -P option is given, print the diagonal fp.diag and the number of
278
short vectors on ISOM.tmp */
279
{
280
outfile = fopen("ISOM.tmp", "a");
281
fprintf(outfile, "%d short vectors\n", 2*V.n);
282
fprintf(outfile, "fingerprint diagonal:\n");
283
for (i = 0; i < dim; ++i)
284
fprintf(outfile, " %2d", fp.diag[i]);
285
fprintf(outfile, "\n");
286
fclose(outfile);
287
}
288
/* get the standard basis in the new order */
289
if ((vec = (int*)malloc(dim * sizeof(int))) == 0)
290
exit (2);
291
for (i = 0; i < dim; ++i)
292
{
293
for (j = 0; j < dim; ++j)
294
vec[j] = 0;
295
vec[fp.per[i]] = 1;
296
fp.e[i] = numberof(vec, V);
297
if (abs(fp.e[i]) > V.n)
298
{
299
fprintf(stderr, "Error: standard basis vector nr. %d not found\n", i);
300
exit (3);
301
}
302
}
303
free(vec);
304
/* if the -D option is given, the scalar product combinations and the
305
corresponding vector sums are computed for the basis of the first lattice */
306
if (flags.DEPTH > 0)
307
{
308
if ((comb = (scpcomb*)malloc(dim * sizeof(scpcomb))) == 0)
309
exit (2);
310
for (i = 0; i < dim; ++i)
311
{
312
/* compute the list of scalar product combinations and the corresponding
313
vector sums */
314
scpvecs(&comb[i].list, &sumveclist, i, fp.e, flags.DEPTH, V, F);
315
/* compute a basis for the lattice that is generated by the vector sums and
316
a transformation matrix that expresses the basis in terms of the
317
vector sums */
318
base(&comb[i], &sumvecbase, sumveclist, F.A[0], dim);
319
if (flags.PRINT == 1)
320
/* if the -P option is given, print the rank of the lattice generated by the
321
vector sums on level i on ISOM.tmp */
322
{
323
outfile = fopen("ISOM.tmp", "a");
324
fprintf(outfile, "comb[%d].rank = %d\n", i, comb[i].rank);
325
fclose(outfile);
326
}
327
/* compute the coefficients of the vector sums in terms of the basis */
328
coef(&comb[i], sumvecbase, sumveclist, F.A[0], dim);
329
for (j = 0; j <= comb[i].list.n; ++j)
330
free(sumveclist[j]);
331
free(sumveclist);
332
/* compute the scalar products of the base-vectors */
333
scpforms(&comb[i], sumvecbase, F);
334
for (j = 0; j < comb[i].rank; ++j)
335
free(sumvecbase[j]);
336
free(sumvecbase);
337
}
338
}
339
/* the Bacher-polynomials for the first BACHDEP base vectors are computed,
340
if no scalar product was given as an argument, the scalar product is set
341
to 1/2 the norm of the base-vector (with respect to the first form) */
342
if (flags.BACH[0] == 1)
343
{
344
if ((bach = (bachpol*)malloc(flags.BACHDEP * sizeof(bachpol))) == 0)
345
exit (2);
346
for (i = 0; i < flags.BACHDEP; ++i)
347
{
348
if (flags.BACH[2] == 0)
349
/* no scalar product was given as an option */
350
flags.BACHSCP = V.v[fp.e[i]][dim] / 2;
351
/* compute the Bacher-polynomial */
352
bacher(&bach[i], fp.e[i], flags.BACHSCP, V, F.v[0]);
353
if (flags.PRINT == 1)
354
/* if the -P option is given, print the Bacher-polynomial on ISOM.tmp */
355
{
356
outfile = fopen("ISOM.tmp", "a");
357
fprintf(outfile, "Bacher-polynomial of base vector fp.e[%d]:\n", i);
358
fputbach(outfile, bach[i]);
359
fclose(outfile);
360
}
361
}
362
}
363
/* the vectors of the first lattice are no longer required, only their number */
364
nV1 = V.n;
365
for(i=0;i<=V.n;i++)
366
free(V.v[i]);
367
free(V.v);
368
for (i = 0; i < F.n; ++i)
369
{
370
for (j = 1; j <= V.n; ++j)
371
free(F.v[i][j]);
372
free(F.v[i]);
373
}
374
free(F.v);
375
/* FF are the invariant forms of the second lattice */
376
if ((FF.A = (int***)malloc(F.n * sizeof(int**))) == 0)
377
exit (2);
378
FF.n = F.n;
379
FF.dim = dim;
380
/* read the invariant forms of the second lattice */
381
for(i=1;i<F.n;i++)
382
{
383
if(F2[i]->rows != F.dim || F2[i]->cols != F.dim)
384
{
385
printf("Different dimensions of the forms in isometry\n");
386
exit(2);
387
}
388
}
389
for(i=0;i<F.n;i++)
390
{
391
if((FF.A[i] = (int **)malloc(dim *sizeof(int *))) == 0)
392
{
393
printf("realloc of FF.A[%d] failed in isometry\n", i);
394
exit(2);
395
}
396
for(j=0;j<dim;j++)
397
{
398
if((FF.A[i][j] = (int *)malloc(dim *sizeof(int))) == 0)
399
{
400
printf("realloc of FF.A[%d][%d] failed in isometry\n", i, j);
401
exit(2);
402
}
403
for(k=0;k<dim;k++)
404
FF.A[i][j][k] = F2[i]->array.SZ[j][k];
405
}
406
}
407
/* get the short vectors of the second lattice */
408
V.dim = dim;
409
V.len = dim + F.n;
410
V.n = SV2->rows;
411
if((V.v = (int **)malloc((V.n+1) *sizeof(int *))) == 0)
412
{
413
printf("realloc of V.v failed in isometry\n");
414
exit(2);
415
}
416
if((V.v[0] = (int *)malloc(V.len *sizeof(int))) == 0)
417
{
418
printf("realloc of V.v[0] failed in isometry\n");
419
exit(2);
420
}
421
for(j=0;j<V.len;j++)
422
V.v[0][j] = 0;
423
for(i=1;i<=V.n;i++)
424
{
425
if((V.v[i] = (int *)malloc(V.len *sizeof(int))) == 0)
426
{
427
printf("realloc of V.v[%d] failed in isometry\n", i);
428
exit(2);
429
}
430
for(j=0;j<=V.dim;j++)
431
V.v[i][j] = SV2->array.SZ[i-1][j];
432
}
433
/* the first nonzero entry of each vector is made positive and the maximal
434
entry of the vectors is determined */
435
max = 1;
436
for (i = 1; i <= V.n; ++i)
437
{
438
Vvi = V.v[i];
439
for (j = 0; j < dim && Vvi[j] == 0; ++j);
440
if (j < dim && Vvi[j] < 0)
441
{
442
for (k = j; k < dim; ++k)
443
Vvi[k] *= -1;
444
}
445
for (k = j; k < dim; ++k)
446
{
447
if (abs(Vvi[k]) > max)
448
max = abs(Vvi[k]);
449
}
450
}
451
if (max > MAXENTRY)
452
/* there is an entry, which is bigger than MAXENTRY, which might cause overflow,
453
since the program doesn't use long integer arithmetic */
454
{
455
fprintf(stderr, "Error: Found entry %d in short vectors of the second lattice.\nTo avoid overflow, the entries should not exceed %d.\n", max, MAXENTRY);
456
exit (3);
457
}
458
/* V.prime is a prime p, such that the entries of the short vectors remain
459
unchanged under reduction mod p in symmetric form, i.e. -p/2 < x <= p/2 */
460
for (V.prime = 2*max + 1; isprime(V.prime) == 0; ++V.prime);
461
j = F.A[0][0][0];
462
for(k=1;k<dim;k++)
463
{
464
if(F.A[0][k][k] > j)
465
j = F.A[0][k][k];
466
}
467
for(k=0;k<dim;k++)
468
{
469
if(FF.A[0][k][k] > j)
470
V.prime = DEF_PRIME;
471
}
472
/* sort the vectors and delete doublets */
473
sortvecs(&V);
474
/* the norm-vector (i.e. the vector of the norms with respect to the different
475
invariant forms) of each vector must be equal to the norm-vector of one
476
of the vectors from the standard-base of the first lattice */
477
checkvecs(&V, FF, norm);
478
for (i = 1; i <= norm.n; ++i)
479
free(norm.v[i]);
480
free(norm.v);
481
/* FF.v[i][j] is the transposed of the product of the Gram-matrix FF.A[i]
482
with the transposed of the vector V.v[j], which now is a short vector of
483
the second lattice */
484
if ((FF.v = (int***)malloc(FF.n * sizeof(int**))) == 0)
485
exit (2);
486
/* the product of the maximal entry in the short vectors with the maximal entry
487
in FF.v[i] should not exceed MAXNORM to avoid overflow */
488
max = MAXNORM / max;
489
for (i = 0; i < FF.n; ++i)
490
{
491
FAi = FF.A[i];
492
if ((FF.v[i] = (int**)malloc((V.n+1) * sizeof(int*))) == 0)
493
exit (2);
494
Fvi = FF.v[i];
495
for (j = 1; j <= V.n; ++j)
496
{
497
Vvj = V.v[j];
498
if ((Fvi[j] = (int*)malloc(dim * sizeof(int))) == 0)
499
exit (2);
500
Fvij = Fvi[j];
501
for (k = 0; k < dim; ++k)
502
{
503
Fvij[k] = sscp(FAi[k], Vvj, dim);
504
if (abs(Fvij[k]) > max)
505
/* some entry in FF.v[i] is too large */
506
{
507
fprintf(stderr, "Error: Found entry %d in FF.v.\nTo avoid overflow, the entries should not exceed %d.\n", Fvij[k], max);
508
exit (3);
509
}
510
}
511
}
512
}
513
/* G are the automorphisms of the second lattice */
514
if ((G = (int***)malloc(1 * sizeof(int**))) == 0)
515
exit (2);
516
/* nG is the number of automorphisms of the second lattice */
517
nG = 0;
518
if (flags.GEN == 1)
519
/* get the automorphisms, which are already known */
520
{
521
ngen = Erzanz;
522
if ((G = (int***)realloc(G, ngen * sizeof(int**))) == 0)
523
exit (2);
524
fail = 0;
525
i=0;
526
while (nG+fail < ngen)
527
{
528
if (Erz[i]->cols != dim || Erz[i]->rows != dim)
529
{
530
fprintf(stderr, "Error: dimension %d should be %d\n", n, dim);
531
exit (3);
532
}
533
if((G[nG] = (int **)malloc(dim *sizeof(int *))) == 0)
534
{
535
printf("realloc of G[%d] in isometry failed\n", nG);
536
exit(2);
537
}
538
for(j=0;j<dim;j++)
539
{
540
if((G[nG][j] = (int *)malloc(dim *sizeof(int))) == 0)
541
{
542
printf("realloc of G[%d][%d] in isometry failed\n", nG, j);
543
exit(2);
544
}
545
for(k=0;k<dim;k++)
546
G[nG][j][k] = Erz[i]->array.SZ[k][j];
547
}
548
/* check whether the matrix is really an automorphism, i.e. fixes the forms */
549
if (checkgen(G[nG], FF) == 0)
550
/* the matrix is not an automorphism */
551
{
552
++fail;
553
for (j = 0; j < dim; ++j)
554
free(G[nG][j]);
555
free(G[nG]);
556
}
557
else
558
/* the matrix fixes the forms in FF */
559
++nG;
560
i++;
561
}
562
}
563
if (nG == 0)
564
/* if no automorphisms are known at least take -Id */
565
{
566
if ((G[0] = (int**)malloc(dim * sizeof(int*))) == 0)
567
exit (2);
568
for (i = 0; i < dim; ++i)
569
{
570
if ((G[0][i] = (int*)malloc(dim * sizeof(int))) == 0)
571
exit (2);
572
for (j = 0; j < dim; ++j)
573
G[0][i][j] = 0;
574
G[0][i][i] = -1;
575
}
576
nG = 1;
577
}
578
/* now search for an isometry */
579
erg = bs_isometry(V, F, FF, fp, G, nG, comb, bach, flags);
580
/**********************
581
for(i=0;i<nG;i++)
582
{
583
for(j=0;j<dim;j++)
584
free(G[i][j]);
585
free(G[i]);
586
}
587
*************************/
588
free(G);
589
for(i=0;i<F.n;i++)
590
{
591
for(j=0;j<dim;j++)
592
free(F.A[i][j]);
593
free(F.A[i]);
594
}
595
free(F.A);
596
for(i=0;i<FF.n;i++)
597
{
598
for(j=1;j<=V.n;j++)
599
free(FF.v[i][j]);
600
free(FF.v[i]);
601
for(j=0;j<dim;j++)
602
free(FF.A[i][j]);
603
free(FF.A[i]);
604
}
605
free(FF.A); free(FF.v);
606
for(i=0;i<=V.n;i++)
607
free(V.v[i]);
608
free(V.v);
609
if (flags.BACH[0] == 1)
610
{
611
for(i=0;i<flags.BACHDEP;i++)
612
free(bach[i].coef);
613
free(bach);
614
}
615
if (flags.DEPTH > 0)
616
{
617
for(i=0;i<dim;i++)
618
{
619
for(j=0;j<=comb[i].list.n;j++)
620
free(comb[i].coef[j]);
621
free(comb[i].coef);
622
for(j=0;j<=comb[i].list.n;j++)
623
free(comb[i].list.v[j]);
624
free(comb[i].list.v);
625
for(j=0;j<comb[i].rank;j++)
626
free(comb[i].trans[j]);
627
free(comb[i].trans);
628
for(j=0;j<F.n;j++)
629
{
630
for(k=0;k<comb[i].rank;k++)
631
free(comb[i].F[j][k]);
632
free(comb[i].F[j]);
633
}
634
free(comb[i].F);
635
}
636
free(comb);
637
}
638
free(fp.diag); free(fp.per); free(fp.e);
639
if(erg == NULL)
640
return(NULL);
641
erg1 = mat_inv(erg);
642
free_mat(erg);
643
return(erg1);
644
}
645
646
/*
647
@-------------------------------------------------------------------------
648
@ matrix_TYP *perfect_normal_isometry(F1, F2, SV1, SV2, Erz, Erzanz,
649
@ options, P, Panz, Pbase, Pdim)
650
@ matrix_TYP *F1, *F2, *SV1, *SV2, **Erz, **P, **Pbase;
651
@ int Erzanz, *options, Panz, Pdim;
652
@
653
@ The function 'perfect_normal_isometry' calculates a matrix X with
654
@ X * F1 * X^{tr} = F2 and
655
@ X^{-1} * Pbase[i] * X^{-tr} is a matrix in P for 0<= i< Pdim
656
@
657
@
658
@ The arguments are:
659
@ F1: a symmetric positive definite n by n-matrix.
660
@ F2: a symmetric positive definite n by n-matrix.
661
@ SV1: the vectors x in GL_n(Z) (up to sign) with xF1x^{tr} < k,
662
@ where k is the maximal diagonal entry of 'F1'.
663
@ SV2: the vectors x in GL_n(Z) (up to sign) with xF2x^{tr} < k,
664
@ where k is the maximal diagonal entry of 'F1'.
665
@ Erz: matrices of elements of Aut(F2) (if known).
666
@ Erzanz: the number of matrices in 'Erz'.
667
@ options: the same as for the function 'isometry'.
668
@ P: a set of matrices
669
@ Panz: the number of matrices given in 'P'.
670
@ Pbase: a set of matrices
671
@ Pdim: the number of matrices given in 'Pbase'.
672
@
673
@ This function is designed to calculate an isometry of two
674
@ G-perfect forms that is in the normalizer of a group G (the
675
@ generators of G are the matrices 'Erz').
676
@ Then 'P' is the set of matrices given by the Voronoi-directions of 'F1'
677
@ and 'Pbase' a maximal linearly independent subset of the
678
@ Voronoi-directions of 'F2'.
679
@
680
@---------------------------------------------------------------------------
681
@
682
*/
683
684
685
matrix_TYP *perfect_normal_isometry(F1, F2, SV1, SV2, Erz, Erzanz, options, P, Panz, Pbase, Pdim)
686
matrix_TYP *F1, *F2, *SV1, *SV2, **Erz, **P, **Pbase;
687
int Erzanz, *options, Panz, Pdim;
688
{
689
FILE *outfile;
690
bachpol *bach;
691
flagstruct flags;
692
scpcomb *comb;
693
invar F, FF;
694
veclist V, norm;
695
fpstruct fp;
696
int dim, max, fail, *vec;
697
int ***G, nG, ngen, **sumveclist, **sumvecbase;
698
int i, j, k, n, *Vvi, *Vvj, **Fvi, *Fvij, **FAi, nV1;
699
matrix_TYP *erg, *erg1;
700
701
extern int pointer_lower_triangular_mat_comp();
702
extern matrix_TYP *mat_inv();
703
704
if(SV1->rows != SV2->rows)
705
return(NULL);
706
normal_option = TRUE;
707
perpdim = Pdim;
708
perp_no = Panz;
709
/* FF.v[i][j] is the transposed of the product of the Gram-matrix FF.A[i]
710
get the flags from the command line */
711
getflags(&flags, options);
712
if(Erzanz > 0)
713
flags.GEN = 1;
714
else flags.GEN = 0;
715
/* F.n is the number of invariant forms */
716
F.n = 1;
717
if ((F.A = (int***)malloc(F.n * sizeof(int**))) == 0)
718
exit (2);
719
/* read the invariant forms of the first lattice */
720
F.dim = F1->cols;
721
dim = F.dim;
722
if(F1->cols != F1->rows)
723
{
724
printf("Non-square matrix as input for isometry\n");
725
exit(2);
726
}
727
if((F.A[0] = (int **)malloc(dim *sizeof(int *))) == 0)
728
{
729
printf("realloc of F.A[0] failed in isometry\n");
730
exit(2);
731
}
732
for(j=0;j<dim;j++)
733
{
734
if((F.A[0][j] = (int *)malloc(dim *sizeof(int))) == 0)
735
{
736
printf("realloc of F.A[0][%d] failed in isometry\n", j);
737
exit(2);
738
}
739
for(k=0;k<dim;k++)
740
F.A[0][j][k] = F1->array.SZ[j][k];
741
}
742
/* get the short vectors of the first lattice */
743
V.dim = dim;
744
V.len = dim + F.n;
745
V.n = SV1->rows;
746
if((V.v = (int **)malloc((V.n+1) *sizeof(int *))) == 0)
747
{
748
printf("realloc of V.v failed in isometry\n");
749
exit(2);
750
}
751
if((V.v[0] = (int *)malloc(V.len *sizeof(int))) == 0)
752
{
753
printf("realloc of V.v[0] failed in isometry\n");
754
exit(2);
755
}
756
for(j=0;j<V.len;j++)
757
V.v[0][j] = 0;
758
for(i=1;i<=V.n;i++)
759
{
760
if((V.v[i] = (int *)malloc(V.len *sizeof(int))) == 0)
761
{
762
printf("realloc of V.v[%d] failed in isometry\n", i);
763
exit(2);
764
}
765
for(j=0;j<=V.dim;j++)
766
V.v[i][j] = SV1->array.SZ[i-1][j];
767
}
768
/* the first nonzero entry of each vector is made positive and the maximal
769
entry in the vectors is determined */
770
max = 1;
771
for (i = 1; i <= V.n; ++i)
772
{
773
Vvi = V.v[i];
774
for (j = 0; j < dim && Vvi[j] == 0; ++j);
775
if (j < dim && Vvi[j] < 0)
776
{
777
for (k = j; k < dim; ++k)
778
Vvi[k] *= -1;
779
}
780
for (k = j; k < dim; ++k)
781
{
782
if (abs(Vvi[k]) > max)
783
max = abs(Vvi[k]);
784
}
785
}
786
if (max > MAXENTRY)
787
/* there is an entry, which is bigger than MAXENTRY, which might cause overflow,
788
since the program doesn't use long integer arithmetic */
789
{
790
fprintf(stderr, "Error: Found entry %d in short vectors of the first lattice.\nTo avoid overflow, the entries should not exceed %d.\n", max, MAXENTRY);
791
exit (3);
792
}
793
/* sort the vectors and delete doublets */
794
sortvecs(&V);
795
/* the norm-vector (i.e. the vector of the norms with respect to the different
796
invariant forms) of each vector must be equal to the norm-vector of one
797
of the vectors from the standard-base */
798
if ((norm.v = (int**)malloc((dim+1) * sizeof(int*))) == 0)
799
exit (2);
800
norm.n = dim;
801
norm.dim = F.n;
802
norm.len = F.n;
803
for (i = 1; i <= norm.n; ++i)
804
{
805
/* norm.v[i] is the norm combination of the (i-1)-th base-vector */
806
if ((norm.v[i] = (int*)malloc(norm.dim * sizeof(int))) == 0)
807
exit (2);
808
for (k = 0; k < norm.dim; ++k)
809
norm.v[i][k] = F.A[k][i-1][i-1];
810
}
811
sortvecs(&norm);
812
/* delete those vectors, which can not be the image of any vector of the
813
standard-base */
814
checkvecs(&V, F, norm);
815
/* F.v[i][j] is the transposed of the product of the Gram-matrix F.A[i] with the
816
transposed of the vector v[j], hence the scalar product of v[j] and v[k] with
817
respect to the Gram-matrix F.A[i] can be computed as standard scalar product
818
of v[j] and F.v[i][k] */
819
if ((F.v = (int***)malloc(F.n * sizeof(int**))) == 0)
820
exit (2);
821
/* the product of the maximal entry in the short vectors with the maximal entry
822
in F.v[i] should not exceed MAXNORM to avoid overflow */
823
max = MAXNORM / max;
824
for (i = 0; i < F.n; ++i)
825
{
826
FAi = F.A[i];
827
if ((F.v[i] = (int**)malloc((V.n+1) * sizeof(int*))) == 0)
828
exit (2);
829
Fvi = F.v[i];
830
for (j = 1; j <= V.n; ++j)
831
{
832
Vvj = V.v[j];
833
if ((Fvi[j] = (int*)malloc(dim * sizeof(int))) == 0)
834
exit (2);
835
Fvij = Fvi[j];
836
for (k = 0; k < dim; ++k)
837
{
838
Fvij[k] = sscp(FAi[k], Vvj, dim);
839
if (abs(Fvij[k]) > max)
840
/* some entry in F.v[i] is too large */
841
{
842
fprintf(stderr, "Error: Found entry %d in F.v.\nTo avoid overflow, the entries should not exceed %d.\n", Fvij[k], max);
843
exit (3);
844
}
845
}
846
}
847
}
848
/* fp.per is the order in which the images of the base vectors are chosen */
849
if ((fp.per = (int*)malloc(dim * sizeof(int))) == 0)
850
exit (2);
851
/* fp.e[i] is the index in V.v of the i-th vector of the standard-base in the
852
new order */
853
if ((fp.e = (int*)malloc(dim * sizeof(int))) == 0)
854
exit (2);
855
/* fp.diag is the diagonal of the fingerprint in the new order */
856
if ((fp.diag = (int*)malloc(dim * sizeof(int))) == 0)
857
exit (2);
858
/* compute the fingerprint */
859
fingerprint(&fp, F, V);
860
mach_perp_matrices(fp, P, Pbase, dim);
861
pointer_mat_quicksort(perp, 0, perp_no-1, dim, dim, pointer_lower_triangular_mat_comp);
862
if (flags.PRINT == 1)
863
/* if the -P option is given, print the diagonal fp.diag and the number of
864
short vectors on ISOM.tmp */
865
{
866
outfile = fopen("ISOM.tmp", "a");
867
fprintf(outfile, "%d short vectors\n", 2*V.n);
868
fprintf(outfile, "fingerprint diagonal:\n");
869
for (i = 0; i < dim; ++i)
870
fprintf(outfile, " %2d", fp.diag[i]);
871
fprintf(outfile, "\n");
872
fclose(outfile);
873
}
874
/* get the standard basis in the new order */
875
if ((vec = (int*)malloc(dim * sizeof(int))) == 0)
876
exit (2);
877
for (i = 0; i < dim; ++i)
878
{
879
for (j = 0; j < dim; ++j)
880
vec[j] = 0;
881
vec[fp.per[i]] = 1;
882
fp.e[i] = numberof(vec, V);
883
if (abs(fp.e[i]) > V.n)
884
{
885
fprintf(stderr, "Error: standard basis vector nr. %d not found\n", i);
886
exit (3);
887
}
888
}
889
free(vec);
890
/* if the -D option is given, the scalar product combinations and the
891
corresponding vector sums are computed for the basis of the first lattice */
892
if (flags.DEPTH > 0)
893
{
894
if ((comb = (scpcomb*)malloc(dim * sizeof(scpcomb))) == 0)
895
exit (2);
896
for (i = 0; i < dim; ++i)
897
{
898
/* compute the list of scalar product combinations and the corresponding
899
vector sums */
900
scpvecs(&comb[i].list, &sumveclist, i, fp.e, flags.DEPTH, V, F);
901
/* compute a basis for the lattice that is generated by the vector sums and
902
a transformation matrix that expresses the basis in terms of the
903
vector sums */
904
base(&comb[i], &sumvecbase, sumveclist, F.A[0], dim);
905
if (flags.PRINT == 1)
906
/* if the -P option is given, print the rank of the lattice generated by the
907
vector sums on level i on ISOM.tmp */
908
{
909
outfile = fopen("ISOM.tmp", "a");
910
fprintf(outfile, "comb[%d].rank = %d\n", i, comb[i].rank);
911
fclose(outfile);
912
}
913
/* compute the coefficients of the vector sums in terms of the basis */
914
coef(&comb[i], sumvecbase, sumveclist, F.A[0], dim);
915
for (j = 0; j <= comb[i].list.n; ++j)
916
free(sumveclist[j]);
917
free(sumveclist);
918
/* compute the scalar products of the base-vectors */
919
scpforms(&comb[i], sumvecbase, F);
920
for (j = 0; j < comb[i].rank; ++j)
921
free(sumvecbase[j]);
922
free(sumvecbase);
923
}
924
}
925
/* the Bacher-polynomials for the first BACHDEP base vectors are computed,
926
if no scalar product was given as an argument, the scalar product is set
927
to 1/2 the norm of the base-vector (with respect to the first form) */
928
if (flags.BACH[0] == 1)
929
{
930
if ((bach = (bachpol*)malloc(flags.BACHDEP * sizeof(bachpol))) == 0)
931
exit (2);
932
for (i = 0; i < flags.BACHDEP; ++i)
933
{
934
if (flags.BACH[2] == 0)
935
/* no scalar product was given as an option */
936
flags.BACHSCP = V.v[fp.e[i]][dim] / 2;
937
/* compute the Bacher-polynomial */
938
bacher(&bach[i], fp.e[i], flags.BACHSCP, V, F.v[0]);
939
if (flags.PRINT == 1)
940
/* if the -P option is given, print the Bacher-polynomial on ISOM.tmp */
941
{
942
outfile = fopen("ISOM.tmp", "a");
943
fprintf(outfile, "Bacher-polynomial of base vector fp.e[%d]:\n", i);
944
fputbach(outfile, bach[i]);
945
fclose(outfile);
946
}
947
}
948
}
949
/* the vectors of the first lattice are no longer required, only their number */
950
nV1 = V.n;
951
for(i=0;i<=V.n;i++)
952
free(V.v[i]);
953
free(V.v);
954
for (i = 0; i < F.n; ++i)
955
{
956
for (j = 1; j <= V.n; ++j)
957
free(F.v[i][j]);
958
free(F.v[i]);
959
}
960
free(F.v);
961
/* FF are the invariant forms of the second lattice */
962
if ((FF.A = (int***)malloc(F.n * sizeof(int**))) == 0)
963
exit (2);
964
FF.n = F.n;
965
FF.dim = dim;
966
/* read the invariant forms of the second lattice */
967
if((FF.A[0] = (int **)malloc(dim *sizeof(int *))) == 0)
968
{
969
printf("realloc of FF.A[0] failed in isometry\n");
970
exit(2);
971
}
972
for(j=0;j<dim;j++)
973
{
974
if((FF.A[0][j] = (int *)malloc(dim *sizeof(int))) == 0)
975
{
976
printf("realloc of FF.A[0][%d] failed in isometry\n", j);
977
exit(2);
978
}
979
for(k=0;k<dim;k++)
980
FF.A[0][j][k] = F2->array.SZ[j][k];
981
}
982
/* get the short vectors of the second lattice */
983
V.dim = dim;
984
V.len = dim + F.n;
985
V.n = SV2->rows;
986
if((V.v = (int **)malloc((V.n+1) *sizeof(int *))) == 0)
987
{
988
printf("realloc of V.v failed in isometry\n");
989
exit(2);
990
}
991
if((V.v[0] = (int *)malloc(V.len *sizeof(int))) == 0)
992
{
993
printf("realloc of V.v[0] failed in isometry\n");
994
exit(2);
995
}
996
for(j=0;j<V.len;j++)
997
V.v[0][j] = 0;
998
for(i=1;i<=V.n;i++)
999
{
1000
if((V.v[i] = (int *)malloc(V.len *sizeof(int))) == 0)
1001
{
1002
printf("realloc of V.v[%d] failed in isometry\n", i);
1003
exit(2);
1004
}
1005
for(j=0;j<=V.dim;j++)
1006
V.v[i][j] = SV2->array.SZ[i-1][j];
1007
}
1008
/* the first nonzero entry of each vector is made positive and the maximal
1009
entry of the vectors is determined */
1010
max = 1;
1011
for (i = 1; i <= V.n; ++i)
1012
{
1013
Vvi = V.v[i];
1014
for (j = 0; j < dim && Vvi[j] == 0; ++j);
1015
if (j < dim && Vvi[j] < 0)
1016
{
1017
for (k = j; k < dim; ++k)
1018
Vvi[k] *= -1;
1019
}
1020
for (k = j; k < dim; ++k)
1021
{
1022
if (abs(Vvi[k]) > max)
1023
max = abs(Vvi[k]);
1024
}
1025
}
1026
if (max > MAXENTRY)
1027
/* there is an entry, which is bigger than MAXENTRY, which might cause overflow,
1028
since the program doesn't use long integer arithmetic */
1029
{
1030
fprintf(stderr, "Error: Found entry %d in short vectors of the second lattice.\nTo avoid overflow, the entries should not exceed %d.\n", max, MAXENTRY);
1031
exit (3);
1032
}
1033
/* V.prime is a prime p, such that the entries of the short vectors remain
1034
unchanged under reduction mod p in symmetric form, i.e. -p/2 < x <= p/2 */
1035
for (V.prime = 2*max + 1; isprime(V.prime) == 0; ++V.prime);
1036
/* sort the vectors and delete doublets */
1037
sortvecs(&V);
1038
/* the norm-vector (i.e. the vector of the norms with respect to the different
1039
invariant forms) of each vector must be equal to the norm-vector of one
1040
of the vectors from the standard-base of the first lattice */
1041
checkvecs(&V, FF, norm);
1042
for (i = 1; i <= norm.n; ++i)
1043
free(norm.v[i]);
1044
free(norm.v);
1045
/* FF.v[i][j] is the transposed of the product of the Gram-matrix FF.A[i]
1046
with the transposed of the vector V.v[j], which now is a short vector of
1047
the second lattice */
1048
if ((FF.v = (int***)malloc(FF.n * sizeof(int**))) == 0)
1049
exit (2);
1050
/* the product of the maximal entry in the short vectors with the maximal entry
1051
in FF.v[i] should not exceed MAXNORM to avoid overflow */
1052
max = MAXNORM / max;
1053
for (i = 0; i < FF.n; ++i)
1054
{
1055
FAi = FF.A[i];
1056
if ((FF.v[i] = (int**)malloc((V.n+1) * sizeof(int*))) == 0)
1057
exit (2);
1058
Fvi = FF.v[i];
1059
for (j = 1; j <= V.n; ++j)
1060
{
1061
Vvj = V.v[j];
1062
if ((Fvi[j] = (int*)malloc(dim * sizeof(int))) == 0)
1063
exit (2);
1064
Fvij = Fvi[j];
1065
for (k = 0; k < dim; ++k)
1066
{
1067
Fvij[k] = sscp(FAi[k], Vvj, dim);
1068
if (abs(Fvij[k]) > max)
1069
/* some entry in FF.v[i] is too large */
1070
{
1071
fprintf(stderr, "Error: Found entry %d in FF.v.\nTo avoid overflow, the entries should not exceed %d.\n", Fvij[k], max);
1072
exit (3);
1073
}
1074
}
1075
}
1076
}
1077
/* G are the automorphisms of the second lattice */
1078
if ((G = (int***)malloc(1 * sizeof(int**))) == 0)
1079
exit (2);
1080
/* nG is the number of automorphisms of the second lattice */
1081
nG = 0;
1082
if (flags.GEN == 1)
1083
/* get the automorphisms, which are already known */
1084
{
1085
ngen = Erzanz;
1086
if ((G = (int***)realloc(G, ngen * sizeof(int**))) == 0)
1087
exit (2);
1088
fail = 0;
1089
i=0;
1090
while (nG+fail < ngen)
1091
{
1092
if (Erz[i]->cols != dim || Erz[i]->rows != dim)
1093
{
1094
fprintf(stderr, "Error: dimension %d should be %d\n", n, dim);
1095
exit (3);
1096
}
1097
if((G[nG] = (int **)malloc(dim *sizeof(int *))) == 0)
1098
{
1099
printf("realloc of G[%d] in isometry failed\n", nG);
1100
exit(2);
1101
}
1102
for(j=0;j<dim;j++)
1103
{
1104
if((G[nG][j] = (int *)malloc(dim *sizeof(int))) == 0)
1105
{
1106
printf("realloc of G[%d][%d] in isometry failed\n", nG, j);
1107
exit(2);
1108
}
1109
for(k=0;k<dim;k++)
1110
G[nG][j][k] = Erz[i]->array.SZ[k][j];
1111
}
1112
/* check whether the matrix is really an automorphism, i.e. fixes the forms */
1113
if (checkgen(G[nG], FF) == 0)
1114
/* the matrix is not an automorphism */
1115
{
1116
++fail;
1117
for (j = 0; j < dim; ++j)
1118
free(G[nG][j]);
1119
free(G[nG]);
1120
}
1121
else
1122
/* the matrix fixes the forms in FF */
1123
++nG;
1124
i++;
1125
}
1126
}
1127
if (nG == 0)
1128
/* if no automorphisms are known at least take -Id */
1129
{
1130
if ((G[0] = (int**)malloc(dim * sizeof(int*))) == 0)
1131
exit (2);
1132
for (i = 0; i < dim; ++i)
1133
{
1134
if ((G[0][i] = (int*)malloc(dim * sizeof(int))) == 0)
1135
exit (2);
1136
for (j = 0; j < dim; ++j)
1137
G[0][i][j] = 0;
1138
G[0][i][i] = -1;
1139
}
1140
nG = 1;
1141
}
1142
/* now search for an isometry */
1143
erg = bs_isometry(V, F, FF, fp, G, nG, comb, bach, flags);
1144
for(i=0;i<F.n;i++)
1145
{
1146
for(j=0;j<dim;j++)
1147
free(F.A[i][j]);
1148
free(F.A[i]);
1149
}
1150
free(F.A);
1151
for(i=0;i<FF.n;i++)
1152
{
1153
for(j=1;j<=V.n;j++)
1154
free(FF.v[i][j]);
1155
free(FF.v[i]);
1156
for(j=0;j<dim;j++)
1157
free(FF.A[i][j]);
1158
free(FF.A[i]);
1159
}
1160
free(FF.A); free(FF.v);
1161
for(i=0;i<=V.n;i++)
1162
free(V.v[i]);
1163
free(V.v);
1164
if (flags.BACH[0] == 1)
1165
{
1166
for(i=0;i<flags.BACHDEP;i++)
1167
free(bach[i].coef);
1168
free(bach);
1169
}
1170
if (flags.DEPTH > 0)
1171
{
1172
for(i=0;i<dim;i++)
1173
{
1174
for(j=0;j<=comb[i].list.n;j++)
1175
free(comb[i].coef[j]);
1176
free(comb[i].coef);
1177
for(j=0;j<=comb[i].list.n;j++)
1178
free(comb[i].list.v[j]);
1179
free(comb[i].list.v);
1180
for(j=0;j<comb[i].rank;j++)
1181
free(comb[i].trans[j]);
1182
free(comb[i].trans);
1183
for(j=0;j<F.n;j++)
1184
{
1185
for(k=0;k<comb[i].rank;k++)
1186
free(comb[i].F[j][k]);
1187
free(comb[i].F[j]);
1188
}
1189
free(comb[i].F);
1190
}
1191
free(comb);
1192
}
1193
free(fp.diag); free(fp.per); free(fp.e);
1194
/****************************
1195
for(i=0;i<nG;i++)
1196
{
1197
for(j=0;j<dim;j++)
1198
free(G[i][j]);
1199
free(G[i]);
1200
}
1201
*********************/
1202
free(G);
1203
free_perp_matrices(dim);
1204
if(erg == NULL)
1205
return(NULL);
1206
erg1 = mat_inv(erg);
1207
free_mat(erg);
1208
return(erg1);
1209
}
1210
1211