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
/****************************************************************************
2
@
3
@ ----------------------------------------------------------------------------
4
@
5
@ FILE: normalop.c
6
@
7
@ ----------------------------------------------------------------------------
8
@
9
******************************************************************************/
10
11
#include <typedef.h>
12
#include <getput.h>
13
#include <matrix.h>
14
#include <base.h>
15
#include <gmp.h>
16
#include <zass.h>
17
#include <longtools.h>
18
#include <orbit.h>
19
#include <sort.h>
20
#include <bravais.h>
21
#include <contrib.h>
22
23
#define TWOTO21 2097152
24
25
extern int INFO_LEVEL;
26
27
static void mod(int *a,int b)
28
{
29
a[0] = a[0] % b;
30
if (a[0]<0) a[0] += b;
31
}
32
33
void valuation(matrix_TYP *x,matrix_TYP *D,MP_INT *val)
34
{
35
int first,
36
last,
37
i;
38
39
MP_INT prod,
40
tmp;
41
42
mpz_init_set_si(&prod,1);
43
mpz_set_si(val,0);
44
mpz_init(&tmp);
45
46
/* set first and last */
47
for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);
48
for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);
49
50
for (i=first;i<last;i++){
51
mod(x->array.SZ[i-first],D->array.SZ[i][i]);
52
mpz_mul_ui(&tmp,&prod,(unsigned long ) x->array.SZ[i-first][0]);
53
mpz_add(val,val,&tmp);
54
mpz_mul_ui(&prod,&prod,(unsigned long) D->array.SZ[i][i]);
55
}
56
57
mpz_clear(&prod);
58
mpz_clear(&tmp);
59
60
return;
61
} /* valuation(.....) */
62
63
static int hash(struct tree *p,MP_INT *valuations,MP_INT *new_val,int pos)
64
{
65
66
int cmp;
67
68
if ((p==NULL) || (p->no <0)){
69
fprintf(stderr,"fehler in hash\n");
70
}
71
72
cmp = mpz_cmp(new_val,valuations+p->no);
73
74
if (cmp < 0){
75
if (p->left == NULL){
76
if (pos != -1){
77
p->left = (struct tree *) calloc(1,sizeof(struct tree));
78
p->left->no = pos;
79
}
80
return -1;
81
}
82
else{
83
return hash(p->left,valuations,new_val,pos);
84
}
85
}
86
else if (cmp > 0){
87
if (p->right == NULL){
88
if (pos != -1){
89
p->right = (struct tree *) calloc(1,sizeof(struct tree));
90
p->right->no = pos;
91
}
92
return -1;
93
}
94
else{
95
return hash(p->right,valuations,new_val,pos);
96
}
97
}
98
else{
99
return p->no;
100
}
101
102
} /* static int hash(...) */
103
104
static int smallest(struct tree *p)
105
{
106
if (p==NULL){
107
printf("error in smallest\n");
108
exit(3);
109
}
110
111
if (p->left == NULL){
112
return p->no;
113
}
114
else{
115
return smallest(p->left);
116
}
117
118
} /* static int smallest(...) */
119
120
/**************************************************************************
121
@
122
@ -------------------------------------------------------------------------
123
@
124
@ matrix_TYP *orbit_rep(matrix_TYP *x,
125
@ matrix_TYP **N,
126
@ int nanz,
127
@ matrix_TYP *D,
128
@ int option,
129
@ char *B,
130
@ MP_INT *l,
131
@ int *anz,
132
@ int **word,
133
@ int word_flag,
134
@ int ***WORDS,
135
@ int *NUMBER_OF_WORDS)
136
@
137
@
138
@ option: an integer controling the behaviours of the function.
139
@ option = 0: return the length of the orbit via anz[0] and
140
@ the smallest representative via return.
141
@ option = 1: return straight if we found a smaller
142
@ representative, and return this one.
143
@ anz[0] has no defined meaning in this case.
144
@ char *B:
145
@
146
@ l: the valuation of the representative returned is via
147
@ this pointer.
148
@
149
@ int **word: needed only for word_flag==TRUE:
150
@ returns a list of integers word with the following property:
151
@ N[word[0][1]] * N[word[0][2]] * ... *N[word[0][word[0][0]]
152
@ is a word representing the smallest representative in the
153
@ orbit.
154
@ int word_flag: drives the behaviour of the function:
155
@ for word_flag == TRUE it calculates such a word described
156
@ above, otherwise it will not change word[0] (hopefully).
157
@ int ***WORDS:
158
@ int *NUMBER_OF_WORDS:
159
@
160
@ Neither the matrices given nor any global variable is changed.
161
@
162
@ -------------------------------------------------------------------------
163
@
164
***************************************************************************/
165
matrix_TYP *orbit_rep(matrix_TYP *x,
166
matrix_TYP **N,
167
int nanz,
168
matrix_TYP *D,
169
int option,
170
char *B,
171
MP_INT *l,
172
int *anz,
173
int **word,
174
int word_flag,
175
int ***WORDS,
176
int *NUMBER_OF_WORDS)
177
{
178
int first,
179
last,
180
i,
181
j,
182
k,
183
h,
184
**orb_words,
185
speicher; /* the number of allocated memory for valuations
186
and orbit, and orb_words */
187
MP_INT *valuations,
188
new_val; /* the valuation of the newly calculated vector */
189
190
matrix_TYP *erg,
191
**orbit,
192
*tmp;
193
194
struct tree *p;
195
196
/* set first and last */
197
for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);
198
for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);
199
200
/* get memory */
201
p = (struct tree *) calloc(1,sizeof(struct tree));
202
speicher = MIN_SPEICHER;
203
valuations = (MP_INT *) malloc(speicher * sizeof(MP_INT));
204
for (i=0;i<speicher;i++) mpz_init(&valuations[i]);
205
mpz_init(&new_val);
206
orbit = (matrix_TYP **) malloc(speicher * sizeof(matrix_TYP*));
207
orbit[0] = copy_mat(x);
208
if (word_flag){
209
orb_words = (int **) malloc(speicher * sizeof(int ));
210
orb_words[0] = (int *) malloc(sizeof(int));
211
orb_words[0][0] = 0;
212
}
213
valuation(x,D,&valuations[0]);
214
215
/* anz[0] is the length of the orbit so far */
216
anz[0] = 1;
217
erg = NULL;
218
219
for (i=0;i<anz[0] && erg == NULL;i++){
220
for (j=0;j<nanz && erg == NULL;j++){
221
tmp = mat_mul(N[j],orbit[i]);
222
223
/* normalize tmp modulo the diagonal entries of D */
224
for (k=first;k<last;k++)
225
mod(tmp->array.SZ[k-first],D->array.SZ[k][k]);
226
227
valuation(tmp,D,&new_val);
228
229
h = hash(p,valuations,&new_val,anz[0]);
230
231
if (h != (-1)){
232
/* the element is not new */
233
free_mat(tmp);
234
235
/* inserted this case to handle the stabilizer of a cozycle
236
as well: tilman 15.03. */
237
if (WORDS){
238
239
/* we got a new generator of the stabilizer of the cozycle */
240
WORDS[0][NUMBER_OF_WORDS[0]] = (int *) calloc(
241
orb_words[h][0]+orb_words[i][0]+2, sizeof(int));
242
WORDS[0][NUMBER_OF_WORDS[0]][0] =
243
orb_words[h][0]+orb_words[i][0]+1;
244
for (k=1;k<=orb_words[h][0];k++){
245
WORDS[0][NUMBER_OF_WORDS[0]][k] =
246
-orb_words[h][orb_words[h][0] - k + 1] - 1;
247
}
248
WORDS[0][NUMBER_OF_WORDS[0]][orb_words[h][0]+1] = j+1;
249
for (k=1;k<=orb_words[i][0];k++){
250
WORDS[0][NUMBER_OF_WORDS[0]][orb_words[h][0]+1+k] =
251
orb_words[i][k] + 1;
252
}
253
254
NUMBER_OF_WORDS[0]++;
255
if (NUMBER_OF_WORDS[0] % MIN_SPEICHER)
256
WORDS[0] = (int **) realloc( WORDS[0] ,
257
(NUMBER_OF_WORDS[0]+MIN_SPEICHER) * sizeof(int));
258
}
259
}
260
else{
261
/* the element is new */
262
263
/* get more memory is nessesary */
264
if (anz[0] >= speicher){
265
speicher += MIN_SPEICHER;
266
valuations = (MP_INT *) realloc(valuations,
267
speicher * sizeof(MP_INT));
268
for (k=anz[0];k<speicher;k++) mpz_init(&valuations[k]);
269
orbit = (matrix_TYP **) realloc(orbit,
270
speicher * sizeof(matrix_TYP *));
271
if (word_flag){
272
orb_words = realloc(orb_words,speicher * sizeof(int));
273
}
274
}
275
276
mpz_set(valuations+anz[0],&new_val);
277
orbit[anz[0]] = tmp;
278
anz[0]++;
279
280
if (word_flag){
281
orb_words[anz[0]-1] = (int *) malloc( (orb_words[i][0] + 2)
282
* sizeof(int));
283
memcpy(orb_words[anz[0]-1]+2,orb_words[i]+1,(orb_words[i][0])
284
* sizeof(int));
285
orb_words[anz[0]-1][0] = orb_words[i][0] + 1;
286
orb_words[anz[0]-1][1] = j;
287
}
288
289
/* here is the place to check whether the option allows us
290
to exit straigth if tmp is small enough */
291
if ((option == 1) && (mpz_cmp(&new_val,&valuations[0])<0)){
292
erg = tmp;
293
mpz_set(l,&new_val);
294
anz[0]--;
295
}
296
297
/* mark this element got in the element list B */
298
if (B!= NULL) B[mpz_get_ui(&new_val)] = TRUE;
299
}
300
}
301
}
302
303
/* now get the smallest representative if nessesary */
304
if (option == 0 || (option == 1 && erg == NULL)){
305
k = smallest(p);
306
erg = copy_mat(orbit[k]);
307
mpz_set(l,&valuations[k]);
308
if (word_flag){
309
word[0] = orb_words[k];
310
/* just malloced to be able to free it */
311
orb_words[k] = (int *) malloc(1*sizeof(int));
312
}
313
}
314
315
/* cleaning up */
316
for (i=0;i<anz[0];i++) free_mat(orbit[i]);
317
free(orbit);
318
for (i=0;i<speicher;i++) mpz_clear(valuations+i);
319
free(valuations);
320
free_tree(p);
321
mpz_clear(&new_val);
322
if (word_flag){
323
for (i=0;i<anz[0];i++) free(orb_words[i]);
324
free(orb_words);
325
}
326
327
return erg;
328
}
329
330
331
332
/**************************************************************************
333
@
334
@ -------------------------------------------------------------------------
335
@
336
@ matrix_TYP *normalop(matrix_TYP *cozycle,matrix_TYP *D,matrix_TYP *R,
337
@ bravais_TYP *G,matrix_TYP *N)
338
@
339
@ Calculates the action of the matrix N on the cohomology group H^1(G,*)
340
@ described by the matrices cozycle, D, R, which are in turn output of
341
@ cohomology.
342
@
343
@ CAUTION: The matrix returned describes the action on rows, and it is
344
@ not checked whether N is realy an element of the normalizer of G!
345
@
346
@ matrix_TYP *cozycle: the first return value of cohomology for G.
347
@ matrix_TYP *D: the second return value of cohomology for G.
348
@ matrix_TYP *R: the third return value of cohomology for G.
349
@ bravais_TYP *G: the group. only the field generator is realy needed.
350
@ matrix_TYP *N: the matrix in question.
351
@ int opt:
352
@
353
@ No global variables nor the arguments are changed (hopefully).
354
@
355
@ -------------------------------------------------------------------------
356
@
357
***************************************************************************/
358
matrix_TYP *normalop(matrix_TYP *cozycle,
359
matrix_TYP *D,
360
matrix_TYP *R,
361
bravais_TYP *G,
362
matrix_TYP *N,
363
int opt)
364
365
{
366
int i,
367
j,
368
k,
369
denominator,
370
first, /* first index such that D[i][i] != 1 */
371
last; /* last index with D[i][i] !=0 */
372
373
int **words; /* the words which give the original generators
374
will be stored in here by reget_gen */
375
376
matrix_TYP *tmp,
377
*tmp2,
378
*sols,
379
*new_coz, /* the mapped cozycle */
380
*Ninv, /* hold's the inverse of N */
381
**map, /* hold's the map of a pair generator/cozycle under N */
382
*erg; /* describes the result */
383
384
static matrix_TYP *GLS;
385
386
Ninv = mat_inv(N);
387
erg = init_mat(cozycle->cols,cozycle->cols,"");
388
map = (matrix_TYP **) malloc(G->gen_no * sizeof(matrix_TYP *));
389
for (i=0;i<G->gen_no;i++){
390
map[i] = init_mat(G->dim+1,G->dim+1,"1");
391
}
392
393
/* get memory for the words */
394
words = (int **) malloc(G->gen_no * sizeof(int *));
395
396
/* set first and last */
397
for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);
398
for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);
399
400
if (GLS == NULL){
401
GLS = long_mat_inv(R);
402
}
403
404
if (INFO_LEVEL & 4){
405
fprintf(stderr,"entered normalop\n");
406
put_mat(N,NULL,"N",2);
407
put_mat(Ninv,NULL,"Ninv",2);
408
put_mat(GLS,NULL,"GLS",2);
409
}
410
411
/* we take a generating set of the cozycles and let this
412
normalizer element operate */
413
for (i=first;i<last;i++){
414
/* map the i-th cozycle */
415
for (j=0;j<G->gen_no;j++){
416
/* map the jth generator */
417
tmp = mat_kon(N,G->gen[j],Ninv);
418
419
/* store it in the right place */
420
for (k=0;k<tmp->rows;k++){
421
memcpy(map[j]->array.SZ[k],tmp->array.SZ[k],
422
sizeof(int) * tmp->cols);
423
}
424
425
free_mat(tmp);
426
427
/* now map the cozycle */
428
tmp = init_mat(G->dim,1,"");
429
for (k=0;k<tmp->rows;k++)
430
tmp->array.SZ[k][0] = cozycle->array.SZ[j*G->dim + k][i-first];
431
432
tmp2 = mat_mul(N,tmp);
433
free_mat(tmp);
434
435
for (k=0;k<tmp->rows;k++)
436
map[j]->array.SZ[k][G->dim] = tmp2->array.SZ[k][0];
437
free_mat(tmp2);
438
439
if (INFO_LEVEL & 16){
440
Check_mat(map[j]);
441
printf("map of the %d-th gen/coz\n",j);
442
put_mat(map[j],NULL,"map[j]",2);
443
}
444
}
445
446
/* reget the original generators of the group,
447
bare in mind that we got words for i>first already */
448
new_coz = reget_gen(map,G->gen_no,G,words,i==first);
449
450
/* now we are able to express this new cozycle in terms of the "basis" */
451
/* solve the resulting linear system of equations */
452
sols = mat_mul(GLS,new_coz);
453
454
if (INFO_LEVEL & 16){
455
put_mat(sols,NULL,"sols",2);
456
put_mat(new_coz,NULL,"new_coz",2);
457
}
458
459
/* copy the solution to the COLUMNS of erg, so erg will
460
act on COLUMNS as well */
461
for (k=0;k<erg->rows;k++){
462
j = sols->array.SZ[k+first][0] * D->array.SZ[k+first][k+first];
463
denominator = D->array.SZ[i][i];
464
if ((j % denominator)!=0){
465
fprintf(stderr,"error in normalop\n");
466
exit(3);
467
}
468
else{
469
erg->array.SZ[k][i-first] = (j / denominator) %
470
D->array.SZ[k+first][k+first];
471
if (erg->array.SZ[k][i-first] < 0)
472
erg->array.SZ[k][i-first] += D->array.SZ[k+first][k+first];
473
}
474
}
475
476
free_mat(sols);
477
free_mat(new_coz);
478
479
}
480
481
/* cleaning up */
482
free_mat(Ninv);
483
for (i=0;i<G->gen_no;i++){
484
free_mat(map[i]);
485
free(words[i]);
486
}
487
free(map);
488
free(words);
489
490
if (opt){
491
free_mat(GLS);
492
GLS = NULL;
493
}
494
495
return erg;
496
}
497
498
499
void translation(matrix_TYP *TR,
500
matrix_TYP *rep,
501
matrix_TYP *ext,
502
matrix_TYP *cocycle,
503
matrix_TYP *D,
504
bravais_TYP *G)
505
{
506
507
int i,
508
j,
509
k,
510
first,
511
**WORDS;
512
513
matrix_TYP *tmp,
514
*tmp2,
515
**MAP;
516
517
/* set first */
518
for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);
519
520
WORDS = (int **) calloc(G->gen_no , sizeof(int*));
521
522
tmp2 = long_mat_inv(TR);
523
MAP = (matrix_TYP **) malloc(G->gen_no * sizeof(matrix_TYP *));
524
for (j=0;j<G->gen_no;j++){
525
MAP[j] = copy_mat(G->gen[j]);
526
real_mat(MAP[j],MAP[j]->rows+1,MAP[j]->cols);
527
real_mat(MAP[j],MAP[j]->rows,MAP[j]->cols+1);
528
MAP[j]->array.SZ[G->dim][G->dim] = 1;
529
for (k=0;k<G->dim;k++){
530
MAP[j]->array.SZ[k][G->dim]=ext->array.SZ[j*G->dim+k][0];
531
}
532
tmp = mat_kon(TR,MAP[j],tmp2);
533
free_mat(MAP[j]);
534
MAP[j] = tmp;
535
}
536
tmp = reget_gen(MAP,G->gen_no,G,WORDS,TRUE);
537
tmp->kgv = ext->kgv;
538
539
for (i=0;i<G->gen_no;i++){
540
free_mat(MAP[i]);
541
free(WORDS[i]);
542
}
543
free(MAP);
544
free(WORDS);
545
546
for (i=0;i<rep->rows;i++){
547
k = rep->array.SZ[i][0] * tmp->kgv / D->array.SZ[first+i][first+i];
548
if (k != 0){
549
for (j=0;j<tmp->rows;j++){
550
tmp->array.SZ[j][0] -= k * cocycle->array.SZ[j][i];
551
}
552
}
553
}
554
555
coboundary(G,tmp,TR);
556
free_mat(tmp2);
557
free_mat(tmp);
558
559
return;
560
561
}
562
563
/**************************************************************************
564
@
565
@--------------------------------------------------------------------------
566
@
567
@ matrix_TYP **identify(matrix_TYP *cozycle,
568
@ matrix_TYP *D,
569
@ matrix_TYP *R,
570
@ bravais_TYP *G,
571
@ matrix_TYP **extension,
572
@ MP_INT *a,
573
@ int number,
574
@ int transform_flag,
575
@ int ***WORDS,
576
@ int *NUMBER_OF_WORDS)
577
@
578
@ Identifies the space groups described by the cozycles in extension,
579
@ i.e. gives them different number iff they are not isomorphic.
580
@ The return value depends on the value of transform_flag. If
581
@ (transform_flag == TRUE) it will return a list of "number" matrices in
582
@ the normalizer of the point group which transforms each given extension
583
@ into it's least representative. This is usefull to calculate the
584
@ isomorphism between two extensions which get the same name.
585
@ NOTE: the name given to an extension is 0 (interpreted as MP_INT) iff
586
@ the extension splits.
587
@
588
@ matrix_TYP *cozykle: 1st matrix returned by cohomolgy for G.
589
@ matrix_TYP *D: 2nd matrix returned by cohomolgy for G.
590
@ matrix_TYP *R: 3rd matrix returned by cohomolgy for G.
591
@ bravais_TYP *G: the group in question. Needed are the
592
@ fields G->gen, G->gen_no, G->cen,G->cen_no,
593
@ G->normal,G->normal_no.
594
@ Important for the correctness of the result
595
@ is that the matrices in G->cen, G->normal
596
@ generate N_GL_n(Z) (G) /G.
597
@ matrix_TYP **extension: matrices discribing a cozycles for the group G.
598
@ So each matrix in the list discribes a spacegroup.
599
@ MP_int *a: The names for the groups will be returned
600
@ via this field. The space has to be allocated
601
@ via malloc and to be mpz_init-ed for each
602
@ entry before calling the function.
603
@ int number: The number of matrices in extension.
604
@ int transform_flag: if (transform_flag) the function will return
605
@ a pointer containing "number" matrices which
606
@ transform each extension into it's least
607
@ representative. Otherwise it will return NULL.
608
@ int ***WORDS: words in the generators of the normalizer
609
@ which generate the stabilizer og this cozykle
610
@ as a subgroup. If == NULL, this is not calculated.
611
@ Otherwise it is an address of a dynamic pointer
612
@ to at least MIN_SPEICHER entries of type *int.
613
@ int *NUMBER_OF_WORDS: number of words WORDS.
614
@--------------------------------------------------------------------------
615
@
616
***************************************************************************/
617
matrix_TYP **identify(matrix_TYP *cozycle,
618
matrix_TYP *D,
619
matrix_TYP *R,
620
bravais_TYP *G,
621
matrix_TYP **extension,
622
MP_INT *a,
623
int number,
624
int transform_flag,
625
int ***WORDS,
626
int *NUMBER_OF_WORDS)
627
{
628
629
int i,
630
j,
631
k,
632
denominator,
633
first,
634
*word, /* the function orbit_rep will return
635
a word representing the least extension
636
by this pointer */
637
Nanz= G->cen_no+G->normal_no;
638
639
matrix_TYP **N,
640
**TR, /* holds the result, ie. the transformation
641
matrices */
642
*GLS,
643
*tmp,
644
*coz,
645
*rep;
646
647
/* set first */
648
for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);
649
650
if (transform_flag)
651
TR = (matrix_TYP **) malloc(number * sizeof(matrix_TYP *));
652
else
653
TR = NULL;
654
655
GLS = mat_inv(R);
656
N = (matrix_TYP **) malloc(Nanz * sizeof(matrix_TYP*));
657
for (i=0;i<Nanz;i++){
658
if (i<G->cen_no){
659
N[i] = normalop(cozycle,D,R,G,G->cen[i],i == (Nanz-1));
660
}
661
else{
662
N[i] = normalop(cozycle,D,R,G,G->normal[i-G->cen_no],i == (Nanz-1));
663
}
664
if (INFO_LEVEL & 16){
665
put_mat(N[i],NULL,"N[i]",2);
666
}
667
}
668
669
coz = init_mat(N[0]->rows,1,"");
670
671
for (i=0;i<number;i++){
672
673
/* firstly calculate a representative, and translate it into
674
the representation of C_d1 X ..... X C_dn */
675
tmp = mat_mul(GLS,extension[i]);
676
677
/* and now calculate the smallest representative in the orbit under
678
the action of the normalizer, and it's valuation */
679
for (k=0;k<coz->rows;k++){
680
j = tmp->array.SZ[k+first][0] * D->array.SZ[k+first][k+first];
681
denominator = tmp->kgv;
682
if ((j % denominator)!=0){
683
fprintf(stderr,"error in identify: are you sure this is a cozycle?\n");
684
fprintf(stderr,"If so, please report to the authors: [email protected]\n");
685
exit(3);
686
}
687
else{
688
coz->array.SZ[k][0] = (j / denominator) %
689
D->array.SZ[k+first][k+first];
690
while (coz->array.SZ[k][0] < 0)
691
coz->array.SZ[k][0] += D->array.SZ[k+first][k+first];
692
}
693
}
694
695
rep = orbit_rep(coz,N,Nanz,D,0,NULL,a+i,&j,&word,
696
transform_flag,WORDS,NUMBER_OF_WORDS);
697
698
if (transform_flag){
699
TR[i] = init_mat(G->dim,G->dim,"1");
700
for (j=1;j<=word[0];j++){
701
if (word[j] < G->cen_no){
702
mat_muleq(TR[i],G->cen[word[j]]);
703
}
704
else{
705
mat_muleq(TR[i],G->normal[word[j]-G->cen_no]);
706
}
707
}
708
free(word);
709
710
/* now calculate the coboundary to get it physically nailed */
711
real_mat(TR[i],TR[i]->rows,TR[i]->cols+1);
712
real_mat(TR[i],TR[i]->rows+1,TR[i]->cols);
713
TR[i]->array.SZ[G->dim][G->dim] = 1;
714
715
if (transform_flag == 3){
716
translation(TR[i],rep,extension[i],cozycle,D,G);
717
}
718
}
719
720
/* we are done, so clean up */
721
free_mat(tmp);
722
free_mat(rep);
723
724
}
725
726
/* clean up N, coz and GLS */
727
for (i=0;i<Nanz;i++) free_mat(N[i]);
728
free(N);
729
free_mat(coz);
730
free_mat(GLS);
731
732
return TR;
733
}
734
735
736
static int gives_rise_to_torsionfree_space_group(
737
bravais_TYP *G,
738
matrix_TYP *D,
739
matrix_TYP *cocycle,
740
matrix_TYP *x)
741
{
742
743
bravais_TYP *R; /* holds the space group */
744
745
int i,
746
j,
747
k,
748
*res;
749
750
matrix_TYP *C;
751
752
753
R = init_bravais(G->dim+1);
754
C = convert_to_cozycle(x,cocycle,D);
755
756
R->gen = (matrix_TYP **) malloc(G->gen_no * sizeof(matrix_TYP *));
757
R->gen_no = G->gen_no;
758
for (i=0;i<G->gen_no;i++){
759
R->gen[i] = copy_mat(G->gen[i]);
760
real_mat(R->gen[i],G->dim+1,G->dim+1);
761
R->gen[i]->array.SZ[G->dim][G->dim] = 1;
762
iscal_mul(R->gen[i],C->kgv);
763
R->gen[i]->kgv = C->kgv;
764
}
765
766
/* stick the cocycle in the last column of the matrices generating R */
767
k = 0;
768
for (i=0;i<R->gen_no;i++){
769
for (j=0;j<G->dim;j++){
770
R->gen[i]->array.SZ[j][G->dim] = C->array.SZ[k][0];
771
k++;
772
}
773
Check_mat(R->gen[i]);
774
}
775
776
res = torsionfree(R,&i,&j);
777
i = res[0] ; free(res);
778
779
free_bravais(R);
780
free_mat(C);
781
782
return i;
783
}
784
785
/**************************************************************************
786
@
787
@ -------------------------------------------------------------------------
788
@
789
@ matrix_TYP **extensions(matrix_TYP *cozycle,
790
@ matrix_TYP *D,
791
@ matrix_TYP *R,
792
@ bravais_TYP *G,
793
@ int **lengths,
794
@ MP_INT **names,
795
@ int *number_of_orbits,
796
@ int option)
797
@
798
@ Returns the cozycles which generate the isomorphims classes of
799
@ extensions of G by the natural ZG-module. The split extension is
800
@ represented by an all zero matrix.
801
@
802
@ The arguments are:
803
@ matrix_TYP *cozykle: 1st matrix returned by cohomolgy for G.
804
@ matrix_TYP *D: 2nd matrix returned by cohomolgy for G.
805
@ matrix_TYP *R: 3rd matrix returned by cohomolgy for G.
806
@ bravais_TYP *G: the group in question.
807
@ int **lengths: length[0] returns a pointer to the lengths
808
@ of the orbits respectively
809
@ MP_INT **names: names[0] returns a pointer to the names of
810
@ the cozycles as they would appear in a call
811
@ of identify(.....).
812
@ int *number_of_orbits: the number of orbits the normalizer induces
813
@ on the cohomology group.
814
@ int option : controls the behaviour of the function:
815
@ option & 1: construct only torsion free extensions
816
@ -------------------------------------------------------------------------
817
@
818
***************************************************************************/
819
matrix_TYP **extensions(matrix_TYP *cozycle,
820
matrix_TYP *D,
821
matrix_TYP *R,
822
bravais_TYP *G,
823
int **lengths,
824
MP_INT **names,
825
int *number_of_orbits,
826
int option )
827
{
828
int i,
829
Nanz = G->normal_no + G->cen_no,
830
orbit_length;
831
832
char *tested;
833
834
MP_INT act_val,
835
new_val,
836
got_size,
837
coho_size; /* holds the size of the cohomology group */
838
839
matrix_TYP *x,
840
*y,
841
**N,
842
**erg; /* stores the representatives of the orbits=isomorphism
843
classes of extensions as rational matrices */
844
845
if (INFO_LEVEL & 7){
846
fprintf(stderr,"entered extensions\n");
847
}
848
849
number_of_orbits[0] = 0; /* should be changed to a calculation via burnside's
850
lemma */
851
852
mpz_init_set_si(&act_val,0);
853
mpz_init_set_si(&coho_size,1);
854
mpz_init_set_si(&got_size,0);
855
mpz_init(&new_val);
856
/* the order of the cohomology group in the product of those elementary
857
divisors which are not equal 0 */
858
for (i=0;i<D->cols && D->array.SZ[i][i] != 0;i++)
859
mpz_mul_ui(&coho_size,&coho_size,(unsigned long) D->array.SZ[i][i]);
860
861
erg = (matrix_TYP **) malloc(sizeof(matrix_TYP *));
862
lengths[0] = (int *) malloc(sizeof(int));
863
names[0] = (MP_INT *) malloc(sizeof(MP_INT));
864
N = (matrix_TYP **) malloc(Nanz * sizeof(matrix_TYP *));
865
866
if (mpz_get_ui(&coho_size) < TWOTO21)
867
tested = (char *) calloc(mpz_get_ui(&coho_size), sizeof(char));
868
else
869
tested = NULL;
870
871
for (i=0;i<Nanz;i++){
872
if (i<G->cen_no){
873
N[i] = normalop(cozycle,D,R,G,G->cen[i],i == (Nanz-1));
874
}
875
else{
876
N[i] = normalop(cozycle,D,R,G,G->normal[i-G->cen_no],i == (Nanz-1));
877
}
878
if (INFO_LEVEL & 16){
879
put_mat(N[i],NULL,"N[i]",2);
880
}
881
}
882
883
if (is_option('v')){
884
fprintf(stderr,"The 1-cohomology group has ");
885
mpz_out_str(stderr,10,&coho_size);
886
}
887
888
while((mpz_cmp(&got_size,&coho_size)<0) && (mpz_cmp(&act_val,&coho_size)<0)){
889
890
if (INFO_LEVEL == 17 ||
891
is_option('v')){
892
fprintf(stderr,"Got %d extensions so far\n",*number_of_orbits);
893
}
894
895
if (tested == NULL || !tested[mpz_get_ui(&act_val)]){
896
897
if (tested != NULL) tested[mpz_get_ui(&act_val)] = TRUE;
898
899
x = reverse_valuation(&act_val,D);
900
y = orbit_rep(x,N,Nanz,D,1,tested,&new_val,&orbit_length,
901
NULL,FALSE,NULL,NULL);
902
903
if (INFO_LEVEL & 4){
904
printf("act_val %d\n",(int ) mpz_get_ui(&act_val));
905
put_mat(x,NULL,"x",2);
906
put_mat(y,NULL,"y",2);
907
}
908
909
if (mpz_cmp(&new_val,&act_val) == 0 &&
910
(!(option & 1) ||
911
gives_rise_to_torsionfree_space_group( G, D, cozycle, x))){
912
if (number_of_orbits[0] % MIN_SPEICHER == 0){
913
erg = (matrix_TYP **) realloc(erg,
914
(number_of_orbits[0] + MIN_SPEICHER)*sizeof(matrix_TYP*));
915
lengths[0] = (int *) realloc(lengths[0],
916
(number_of_orbits[0] + MIN_SPEICHER)*sizeof(int));
917
names[0] = (MP_INT *) realloc(names[0],
918
(number_of_orbits[0] + MIN_SPEICHER)*sizeof(MP_INT));
919
}
920
erg[number_of_orbits[0]] = convert_to_cozycle(x,cozycle,D);
921
lengths[0][number_of_orbits[0]] = orbit_length;
922
mpz_init_set(names[0]+number_of_orbits[0],&act_val);
923
number_of_orbits[0]++;
924
mpz_add_ui(&got_size,&got_size,(unsigned long) orbit_length);
925
}
926
927
/* clean up and increase act_val */
928
free_mat(y);
929
free_mat(x);
930
}
931
mpz_add_ui(&act_val,&act_val,1);
932
}
933
934
for (i=0;i<Nanz;i++) free_mat(N[i]);
935
free(N);
936
if (tested != NULL ) free(tested);
937
mpz_clear(&act_val);
938
mpz_clear(&new_val);
939
mpz_clear(&got_size);
940
mpz_clear(&coho_size);
941
942
return erg;
943
} /* extensions (.... ) */
944
945
static matrix_TYP **calc_elements(matrix_TYP **N,matrix_TYP **Ninv,int Nanz,
946
matrix_TYP *D,unsigned long *no_of_elements)
947
{
948
int i,
949
j,
950
k,
951
l,
952
pos, /* position returned by hash_mat */
953
dim, /* the rank of the Z-module the N[i] are acting on */
954
first, /* first index such that D[i][i] != 1 */
955
last; /* last index with D[i][i] !=0 */
956
957
matrix_TYP *tmp,
958
**erg; /* holds all elements of the group */
959
960
struct tree *hash;
961
962
/* set first and last */
963
for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);
964
for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);
965
dim = last-first;
966
967
erg = (matrix_TYP **) malloc(MIN_SPEICHER * sizeof(matrix_TYP *));
968
erg[0] = init_mat(dim,dim,"1");
969
*no_of_elements = 1;
970
hash = (struct tree *) malloc(1*sizeof(struct tree));
971
hash->no = 0;
972
hash->left = hash->right = NULL;
973
974
/* we won't need inverses for the orbit calculation, everything is finite */
975
for (i=0;i<*no_of_elements;i++){
976
for (j=0;j<Nanz;j++){
977
tmp = mat_mul(erg[i],N[j]);
978
979
/* normalize tmp */
980
for (k=0;k<dim;k++)
981
for (l=0;l<dim;l++)
982
mod(tmp->array.SZ[k]+l,D->array.SZ[k+first][k+first]);
983
984
pos = hash_mat(hash,erg,tmp,*no_of_elements);
985
986
if (pos != -1){
987
if (Ninv!=NULL && pos==0) Ninv[j] = erg[i];
988
free_mat(tmp);
989
}
990
else{
991
if (*no_of_elements % MIN_SPEICHER == 0)
992
erg = (matrix_TYP **) realloc(erg,
993
(*no_of_elements + MIN_SPEICHER)*sizeof(matrix_TYP *));
994
995
erg[*no_of_elements] = tmp;
996
no_of_elements[0]++;
997
}
998
}
999
}
1000
1001
free_tree(hash);
1002
1003
return erg;
1004
} /* calc_elements(....) */
1005
1006
1007
/****************************************************************************
1008
@
1009
@----------------------------------------------------------------------------
1010
@
1011
@ static void no_of_fixpoints(MP_INT *res,matrix_TYP *A,matrix_TYP *D)
1012
@
1013
@
1014
@ CAUTION: A->array.SZ, A->cols WILL BE CHANGED!!!!
1015
@----------------------------------------------------------------------------
1016
@
1017
*****************************************************************************/
1018
static void no_of_fixpoints(MP_INT *res,matrix_TYP *A,matrix_TYP *D)
1019
{
1020
int i,
1021
first;
1022
1023
matrix_TYP *tmp;
1024
1025
/* set first */
1026
for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);
1027
1028
/* build a matrix (A-I | D') in A (D' = those parts of D which have non
1029
trivial elementary divisors) */
1030
real_mat(A,A->rows,A->cols+A->rows);
1031
for (i=0;i<A->rows;i++){
1032
A->array.SZ[i][i]--;
1033
A->array.SZ[i][i+A->rows] = D->array.SZ[i+first][i+first];
1034
}
1035
1036
tmp = long_elt_mat(NULL,A,NULL);
1037
1038
mpz_set_ui(res,1);
1039
for (i=0;i<tmp->rows;i++) mpz_mul_ui(res,res,tmp->array.SZ[i][i]);
1040
1041
free_mat(tmp);
1042
}
1043
1044
static int deal_with_small_cohomology_group(matrix_TYP *cozycle,
1045
matrix_TYP *D,
1046
matrix_TYP *R,
1047
bravais_TYP *G,
1048
MP_INT *erg)
1049
{
1050
1051
int i,
1052
anz,
1053
order_of_H=1,
1054
*len;
1055
1056
MP_INT *names;
1057
1058
matrix_TYP **Y;
1059
1060
if (G->dim < 5){
1061
return FALSE;
1062
}
1063
1064
/* if the cohomology is small, it might be better to calculate all
1065
extensions then to calculate all elements of the acting group
1066
example: H^1 = C_6^3, G_acting = GL_3(Z/6Z) */
1067
for (i=0;i < D->cols &&
1068
i < D->rows &&
1069
order_of_H < 10000 &&
1070
D->array.SZ[i][i] != 0;i++,order_of_H *= D->array.SZ[i][i]);
1071
if (order_of_H < 10000){
1072
Y = extensions(cozycle,D,R,G,&len,&names,&anz,0);
1073
1074
for (i=0;i<anz;i++){
1075
free_mat(Y[i]);
1076
mpz_clear(names+i);
1077
}
1078
free(names);
1079
free(Y);
1080
free(len);
1081
mpz_set_si(erg,anz);
1082
return TRUE;
1083
}
1084
1085
return FALSE;
1086
1087
}
1088
1089
/************************************************************************
1090
@
1091
@------------------------------------------------------------------------
1092
@
1093
@ void no_of_extensions(matrix_TYP *cozycle,matrix_TYP *D,
1094
@ matrix_TYP *R,bravais_TYP *G,MP_INT *erg)
1095
@
1096
@------------------------------------------------------------------------
1097
@
1098
*************************************************************************/
1099
void no_of_extensions(matrix_TYP *cozycle,matrix_TYP *D,
1100
matrix_TYP *R,bravais_TYP *G,MP_INT *erg)
1101
{
1102
1103
int Nanz=G->cen_no+G->normal_no,
1104
i;
1105
1106
unsigned long no_of_elements; /* the order of the image of the
1107
normalizer under the map to the
1108
automorphism group of H^1(...) */
1109
1110
MP_INT sum, /* holds the sum over the image of N_GL(Z) in
1111
Aut(H^1(...)) of the number fixpoint */
1112
tmp2,
1113
tmp3;
1114
1115
matrix_TYP **N,
1116
**elements,
1117
*id;
1118
1119
if (deal_with_small_cohomology_group(cozycle, D, R, G, erg)){
1120
return;
1121
}
1122
1123
mpz_init(&sum);
1124
mpz_set_si(&sum,0);
1125
mpz_init(&tmp2);
1126
mpz_set_si(&tmp2,0);
1127
mpz_init(&tmp3);
1128
mpz_set_si(&tmp3,0);
1129
1130
N = (matrix_TYP **) malloc(Nanz * sizeof(matrix_TYP *));
1131
for (i=0;i<Nanz;i++){
1132
if (i<G->cen_no){
1133
N[i] = normalop(cozycle,D,R,G,G->cen[i],i == (Nanz-1));
1134
}
1135
else{
1136
N[i] = normalop(cozycle,D,R,G,G->normal[i-G->cen_no],i == (Nanz-1));
1137
}
1138
if (INFO_LEVEL & 16){
1139
put_mat(N[i],NULL,"N[i]",2);
1140
}
1141
}
1142
1143
/* remove those generators which are == identity for speeding up things */
1144
if (Nanz > 0){
1145
id = init_mat(N[0]->rows,N[0]->rows,"1");
1146
for (i=0;i<Nanz;i++){
1147
if (mat_comp(id,N[i]) == 0){
1148
free_mat(N[i]);
1149
Nanz--;
1150
N[i] = N[Nanz];
1151
}
1152
}
1153
}
1154
1155
if (is_option('v')){
1156
fprintf(stderr,"calculated the action of the normalizer on the\n");
1157
fprintf(stderr,"cohomology group\n");
1158
}
1159
1160
elements = calc_elements(N,NULL,Nanz,D,&no_of_elements);
1161
1162
if (is_option('v')){
1163
fprintf(stderr,"Now I got all elements in the image.\n");
1164
}
1165
1166
for (i=0;i<no_of_elements;i++){
1167
no_of_fixpoints(&tmp2,elements[i],D);
1168
1169
if (INFO_LEVEL & 4){
1170
mpz_out_str(stdout,10,&tmp2);
1171
printf("\n");
1172
}
1173
1174
mpz_add(&tmp3,&sum,&tmp2);
1175
mpz_set(&sum,&tmp3);
1176
/* we won't need this element anymore */
1177
free_mat(elements[i]);
1178
1179
if (is_option('v') && (i % 10 == 0)){
1180
fprintf(stderr,"Done approximately %d percent of the calculation\n",
1181
(int ) ((i*100)/no_of_elements));
1182
}
1183
1184
}
1185
1186
/* divide sum by the image order, and check whether this is possible
1187
at all */
1188
mpz_divmod_ui(&tmp3,&tmp2,&sum,no_of_elements);
1189
mpz_set(erg,&tmp3);
1190
1191
if (INFO_LEVEL & 4){
1192
mpz_out_str(stdout,10,&sum);
1193
printf("\n");
1194
mpz_out_str(stdout,10,erg);
1195
printf("\n");
1196
mpz_out_str(stdout,10,&tmp2);
1197
printf("\n");
1198
}
1199
1200
if (mpz_cmp_si(&tmp2,0) != 0){
1201
printf("error in no_of_extensions\n");
1202
exit(3);
1203
}
1204
1205
for (i=0;i<Nanz;i++) free_mat(N[i]);
1206
free(N);
1207
free(elements);
1208
mpz_clear(&sum);
1209
mpz_clear(&tmp2);
1210
mpz_clear(&tmp3);
1211
1212
return;
1213
} /* no_of_extensions(....) */
1214
1215