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
#include "typedef.h"
2
#include "gmp.h"
3
/* #include "gmp-impl.h" */
4
#include "longtools.h"
5
#include "matrix.h"
6
/**************************************************************************\
7
@---------------------------------------------------------------------------
8
@---------------------------------------------------------------------------
9
@ FILE: long_elt.c
10
@---------------------------------------------------------------------------
11
@---------------------------------------------------------------------------
12
@
13
\**************************************************************************/
14
15
16
17
18
19
/**************************************************************************\
20
@---------------------------------------------------------------------------
21
@ matrix_TYP *long_elt_mat(left_trans, Mat, right_trans)
22
@ matrix_TYP *Mat, *left_trans, *right_trans;
23
@
24
@ calculates the elementary divisors of the matrix Mat, t.m.
25
@ calculates a 'diagonal' matrix D in Gl_n(Z) such that
26
@ L * Mat * R = D for some matrices L and R
27
@ 'left_trans' has to be a matrix of size Mat->rows x Mat->rows
28
@ it is changed to L * left_trans.
29
@ It is possible to start the function with left_trans = NULL.
30
@ 'right_trans' has to be a matrix of size Mat->cols x Mat->cols
31
@ it is changed to right_trans * R.
32
@ It is possible to start the function with right_trans = NULL.
33
@
34
@ The calculations are done using multiple precision integers.
35
@---------------------------------------------------------------------------
36
@
37
\**************************************************************************/
38
matrix_TYP *long_elt_mat(left_trans, Mat, right_trans)
39
matrix_TYP *left_trans, *Mat, *right_trans;
40
{
41
42
int i,j,k,l, m, step, stepclear, flag;
43
int cols, rows, rang;
44
MP_INT **trf, **M, **Mt, *merkpointer, **rtrf, *help, **hilf;
45
matrix_TYP *erg;
46
int t_option, r_t_option;
47
MP_INT a1, a2, x1, x2, y1, y2, merk, g, f, o, pos1, pos2;
48
49
cols = Mat->cols;
50
rows = Mat->rows;
51
if(left_trans != NULL)
52
{
53
t_option = TRUE;
54
if(left_trans->cols != rows)
55
{
56
printf("error in 'long_elt_mat':\n");
57
printf("the matrix 'left_trans' has to be a %dx%d-matrix, but has %d columns\n", rows, cols, left_trans->cols);
58
exit(3);
59
}
60
if(left_trans->cols != left_trans->rows)
61
{
62
printf("error: matrix 'left_trans' in 'long_elt_mat' has to be a square matrix\n");
63
exit(3);
64
}
65
}
66
else
67
t_option = FALSE;
68
69
/* inserted the next 17 lines: oliver 2/3/1999 */
70
if(right_trans != NULL)
71
{
72
r_t_option = TRUE;
73
if(right_trans->rows != cols)
74
{
75
printf("error in 'long_elt_mat':\n");
76
printf("the matrix 'right_trans' has to be a %dx%d-matrix, but has %d rows\n", cols, cols, left_trans->rows);
77
exit(3);
78
}
79
if(left_trans->cols != left_trans->rows)
80
{
81
printf("error: matrix 'left_trans' in 'long_elt_mat' has to be a square matrix\n");
82
exit(3);
83
}
84
}
85
else
86
r_t_option = FALSE;
87
88
mpz_init(&a1), mpz_init(&a2);
89
mpz_init(&x1), mpz_init(&x2);
90
mpz_init(&y1), mpz_init(&y2);
91
mpz_init(&f), mpz_init(&g); mpz_init(&o);
92
mpz_init(&merk); mpz_init(&pos1); mpz_init(&pos2);
93
94
/***************************************************************\
95
| (inserted the next 33 lines: oliver 29/4/1999)
96
| Set hilf = right_trans^tr
97
\***************************************************************/
98
if(r_t_option == TRUE)
99
{
100
if((rtrf = (MP_INT **)malloc(cols *sizeof(MP_INT *))) == NULL)
101
{
102
printf("malloc of 'rtrf' in 'long_elt_mat' failed\n");
103
exit(2);
104
}
105
for(i=0;i<cols;i++)
106
{
107
if((rtrf[i] = (MP_INT *)malloc(cols *sizeof(MP_INT))) == NULL)
108
{
109
printf("malloc of 'rtrf[%d]' in 'long_elt_mat' failed\n", i);
110
exit(2);
111
}
112
}
113
if((hilf = (MP_INT **)malloc(cols *sizeof(MP_INT *))) == NULL)
114
{
115
printf("malloc of 'hilf' in 'long_elt_mat' failed\n");
116
exit(2);
117
}
118
for(i=0;i<cols;i++)
119
{
120
if((hilf[i] = (MP_INT *)malloc(cols *sizeof(MP_INT))) == NULL)
121
{
122
printf("malloc of 'hilf[%d]' in 'long_elt_mat' failed\n", i);
123
exit(2);
124
}
125
for(j=0;j<cols;j++)
126
{
127
mpz_init_set_si(&hilf[i][j], right_trans->array.SZ[j][i]);
128
}
129
}
130
}
131
132
/***************************************************************\
133
| Set Mt= Mat^{tr} transform Mt to Hermite normal form.
134
\***************************************************************/
135
if((Mt = (MP_INT **)malloc(cols *sizeof(MP_INT *))) == NULL)
136
{
137
printf("malloc of 'Mt' in 'long_elt_mat' failed\n");
138
exit(2);
139
}
140
for(i=0;i<cols;i++)
141
{
142
if((Mt[i] = (MP_INT *)malloc(rows *sizeof(MP_INT))) == NULL)
143
{
144
printf("malloc of 'Mt[%d]' in 'long_elt_mat' failed\n", i);
145
exit(2);
146
}
147
for(j=0;j<rows;j++)
148
mpz_init_set_si(&Mt[i][j], Mat->array.SZ[j][i]);
149
}
150
151
/* changed on 29/4/1999 oliver from
152
rang = MP_hnf(Mt, cols, rows);
153
to: */
154
if(r_t_option == TRUE)
155
{
156
rang = MP_hnf_simultaneous(Mt, cols, rows, hilf, cols);
157
}
158
else
159
rang = MP_hnf(Mt, cols, rows);
160
161
/***************************************************************\
162
| Set trf = left_trans
163
\***************************************************************/
164
if(t_option == TRUE)
165
{
166
if((trf = (MP_INT **)malloc(rows *sizeof(MP_INT *))) == NULL)
167
{
168
printf("malloc of 'trf' in 'long_elt_mat' failed\n");
169
exit(2);
170
}
171
for(i=0;i<rows;i++)
172
{
173
if((trf[i] = (MP_INT *)malloc(rows *sizeof(MP_INT))) == NULL)
174
{
175
printf("malloc of 'trf[%d]' in 'long_elt_mat' failed\n", i);
176
exit(2);
177
}
178
for(j=0;j<rows;j++)
179
mpz_init_set_si(&trf[i][j], left_trans->array.SZ[i][j]);
180
}
181
}
182
183
/***************************************************************\
184
| Set M= Mt^{tr} transform Mt to Hermite normal form.
185
\***************************************************************/
186
if((M = (MP_INT **)malloc(rows *sizeof(MP_INT *))) == NULL)
187
{
188
printf("malloc of 'M' in 'long_elt_mat' failed\n");
189
exit(2);
190
}
191
for(i=0;i<rows;i++)
192
{
193
if((M[i] = (MP_INT *)malloc(cols *sizeof(MP_INT))) == NULL)
194
{
195
printf("malloc of 'M[%d]' in 'long_elt_mat' failed\n", i);
196
exit(2);
197
}
198
for(j=0;j<cols;j++)
199
mpz_init_set(&M[i][j], &Mt[j][i]);
200
}
201
202
/* the hnf produces big enties in the transformation matrix, there do
203
hnf only if the transformation matrix is not wanted
204
if(t_option == TRUE)
205
rang = MP_hnf_simultaneous(M, rows, cols, trf, rows);
206
else
207
rang = MP_hnf(M, rows, cols); */
208
if(t_option != TRUE)
209
rang = MP_hnf(M, rows, cols);
210
211
/***************************************************************\
212
| Clear the space allocated for 'Mt'.
213
| Set rtrf = hilf^tr and free hilf.
214
\***************************************************************/
215
for(i=0;i<cols;i++)
216
{
217
for(j=0;j<rows;j++)
218
mpz_clear(&Mt[i][j]);
219
free(Mt[i]);
220
}
221
free(Mt);
222
223
if (r_t_option){
224
for (i=0; i<cols; i++)
225
{
226
for(j=0; j<cols; j++)
227
{
228
mpz_init_set(&rtrf[j][i], &hilf[i][j]);
229
mpz_clear(&hilf[i][j]);
230
}
231
free(hilf[i]);
232
}
233
free(hilf);
234
}
235
/***************************************************************\
236
| Now the elementary divisor algorithm starts
237
\***************************************************************/
238
for(step = 0; step < rang; step++)
239
{
240
241
do
242
{
243
/* output for debugging */
244
/* dump_MP_mat(M,rang,rang,"M"); */
245
246
/*------------------------------------------------------*\
247
| Clear the 'step'^th row of M
248
\*------------------------------------------------------*/
249
for(i=step;i<cols && mpz_cmp_si(&M[step][i], 0) == 0; i++);
250
251
if (i<cols){
252
if(i!=step)
253
{
254
for(j=step;j<rows;j++)
255
{
256
mpz_set(&merk, &M[j][step]);
257
mpz_set(&M[j][step], &M[j][i]);
258
mpz_set(&M[j][i], &merk);
259
}
260
261
/* inserted the following 9 lines: oliver 29/4/99 */
262
if (r_t_option == TRUE)
263
{
264
for(j=0;j<cols;j++)
265
{
266
mpz_set(&merk, &rtrf[j][step]);
267
mpz_set(&rtrf[j][step], &rtrf[j][i]);
268
mpz_set(&rtrf[j][i], &merk);
269
}
270
}
271
}
272
273
if(mpz_cmp_si(&M[step][step], 0) < 0)
274
{
275
for(i=step;i<rows;i++)
276
mpz_neg(&M[i][step], &M[i][step]);
277
/* inserted oliver 30/04/99 */
278
if (r_t_option == TRUE)
279
{
280
for(i=0;i<cols;i++)
281
mpz_neg(&rtrf[i][step], &rtrf[i][step]);
282
}
283
}
284
for(i=step+1;i<cols;i++)
285
{
286
if(mpz_cmp_si(&M[step][i], 0) != 0)
287
{
288
if(mpz_cmp_si(&M[step][step], 1) == 0)
289
{
290
mpz_set(&f, &M[step][i]);
291
for(j=step+1;j<rows;j++)
292
{
293
mpz_mul(&merk, &M[j][step], &f);
294
mpz_sub(&M[j][i], &M[j][i], &merk);
295
}
296
mpz_set_si(&M[step][i], 0);
297
298
/* inserted the next 8 lines: oliver 2/3/99 */
299
if(r_t_option == TRUE)
300
{
301
for(j=0;j<cols;j++)
302
{
303
mpz_mul(&merk, &rtrf[j][step], &f);
304
mpz_sub(&rtrf[j][i], &rtrf[j][i], &merk);
305
}
306
}
307
}
308
else
309
{
310
/* changed 30/04/99 (tilman) from
311
mpz_gcdext(&g, &a1, &a2, &M[step][step], &M[step][i]); to */
312
mpz_abs( &g,&M[step][i]);
313
if (mpz_cmp(&M[step][step],&g) == 0){
314
mpz_set_si(&a1,1);
315
mpz_set_si(&a2,0);
316
}
317
else{
318
mpz_gcdext(&g, &a1, &a2, &M[step][step], &M[step][i]);
319
}
320
mpz_div(&x1, &M[step][i], &g);
321
mpz_div(&x2, &M[step][step], &g);
322
mpz_neg(&x2, &x2);
323
324
for(j=step+1; j<rows;j++)
325
{
326
mpz_mul(&y1, &a1, &M[j][step]);
327
mpz_mul(&merk, &a2, &M[j][i]);
328
mpz_add(&y1, &y1, &merk);
329
330
mpz_mul(&y2, &x1, &M[j][step]);
331
mpz_mul(&merk, &x2, &M[j][i]);
332
mpz_add(&y2, &y2, &merk);
333
334
mpz_set(&M[j][step], &y1);
335
mpz_set(&M[j][i], &y2);
336
}
337
338
/* inserted the next 16 lines: oliver 2/3/99 */
339
if(r_t_option == TRUE)
340
{
341
for(j=0; j<cols; j++)
342
{
343
mpz_mul(&y1, &a1, &rtrf[j][step]);
344
mpz_mul(&merk, &a2, &rtrf[j][i]);
345
mpz_add(&y1, &y1, &merk);
346
347
mpz_mul(&y2, &x1, &rtrf[j][step]);
348
mpz_mul(&merk, &x2, &rtrf[j][i]);
349
mpz_add(&y2, &y2, &merk);
350
351
mpz_set(&rtrf[j][step], &y1);
352
mpz_set(&rtrf[j][i], &y2);
353
}
354
}
355
356
mpz_set(&M[step][step], &g);
357
mpz_set_si(&M[step][i], 0);
358
}
359
}
360
}
361
}
362
363
/*------------------------------------------------------*\
364
| Clear the 'step'^th column of M
365
\*------------------------------------------------------*/
366
for(i=step;i<rows && mpz_cmp_si(&M[i][step], 0) == 0; i++);
367
if(i!=step)
368
{
369
merkpointer = M[step];
370
M[step] = M[i];
371
M[i] = merkpointer;
372
if(t_option == TRUE)
373
{
374
merkpointer = trf[step];
375
trf[step] = trf[i];
376
trf[i] = merkpointer;
377
}
378
}
379
if(mpz_cmp_si(&M[step][step], 0) < 0)
380
{
381
for(i=step;i<rows;i++)
382
mpz_neg(&M[i][step], &M[i][step]);
383
384
/* inserted following 5 lines: 30/04/99 oliver */
385
if (r_t_option == TRUE)
386
{
387
for(i=0;i<cols;i++)
388
mpz_neg(&rtrf[i][step], &rtrf[i][step]);
389
}
390
}
391
for(i=step+1;i<rows;i++)
392
{
393
if(mpz_cmp_si(&M[i][step], 0) != 0)
394
{
395
if(mpz_cmp_si(&M[step][step], 1) == 0)
396
{
397
mpz_set(&f, &M[i][step]);
398
for(j=step+1;j<cols;j++)
399
{
400
mpz_mul(&merk, &M[step][j], &f);
401
mpz_sub(&M[i][j], &M[i][j], &merk);
402
}
403
mpz_set_si(&M[i][step], 0);
404
405
/* inserted the next 7 lines: tilman 5/12/96 */
406
if (t_option){
407
for(j=0;j<rows;j++)
408
{
409
mpz_mul(&merk, &trf[step][j], &f);
410
mpz_sub(&trf[i][j], &trf[i][j], &merk);
411
}
412
}
413
414
}
415
else
416
{
417
/* changed on 8/1/97 tilman from
418
mpz_gcdext(&g, &a1, &a2, &M[step][step], &M[i][step]);
419
to : */
420
mpz_abs( &g,&M[i][step]);
421
if (mpz_cmp(&M[step][step],&g) == 0){
422
mpz_set_si(&a1,1);
423
mpz_set_si(&a2,0);
424
}
425
else{
426
mpz_gcdext(&g, &a1, &a2, &M[step][step], &M[i][step]);
427
}
428
429
mpz_div(&x1, &M[i][step], &g);
430
mpz_div(&x2, &M[step][step], &g);
431
mpz_neg(&x2, &x2);
432
433
for(j=step+1; j<cols;j++)
434
{
435
mpz_mul(&y1, &a1, &M[step][j]);
436
mpz_mul(&merk, &a2, &M[i][j]);
437
mpz_add(&y1, &y1, &merk);
438
439
mpz_mul(&y2, &x1, &M[step][j]);
440
mpz_mul(&merk, &x2, &M[i][j]);
441
mpz_add(&y2, &y2, &merk);
442
443
mpz_set(&M[step][j], &y1);
444
mpz_set(&M[i][j], &y2);
445
}
446
447
/* inserted the next 15 lines: tilman 5/12/96 */
448
if (t_option){
449
for(j=0; j<rows;j++)
450
{
451
mpz_mul(&y1, &a1, &trf[step][j]);
452
mpz_mul(&merk, &a2, &trf[i][j]);
453
mpz_add(&y1, &y1, &merk);
454
455
mpz_mul(&y2, &x1, &trf[step][j]);
456
mpz_mul(&merk, &x2, &trf[i][j]);
457
mpz_add(&y2, &y2, &merk);
458
459
mpz_set(&trf[step][j], &y1);
460
mpz_set(&trf[i][j], &y2);
461
}
462
}
463
464
mpz_set(&M[step][step], &g);
465
mpz_set_si(&M[i][step], 0);
466
}
467
}
468
}
469
/*------------------------------------------------------*\
470
| Check whether the column and row are both clear
471
\*------------------------------------------------------*/
472
stepclear = TRUE;
473
for(i=step+1;i<cols && stepclear == TRUE;i++)
474
{
475
if(mpz_cmp_si(&M[step][i], 0) != 0)
476
stepclear = FALSE;
477
}
478
for(i=step+1;i<rows && stepclear == TRUE;i++)
479
{
480
if(mpz_cmp_si(&M[i][step], 0) != 0)
481
stepclear = FALSE;
482
}
483
}while(stepclear == FALSE);
484
if(mpz_cmp_si(&M[step][step], 0) < 0)
485
{
486
mpz_neg(&M[step][step], &M[step][step]);
487
488
/* inserted next 6 lines: oliver 2/5/99 */
489
if (r_t_option == TRUE)
490
{
491
for(i=0;i<cols;i++)
492
mpz_neg(&rtrf[i][step], &rtrf[i][step]);
493
}
494
}
495
}
496
497
/*******************************************************************\
498
| Now M is diagonal.
499
| Now one has transform M such that M[i][i] divides M[i+1][i+1]
500
\*******************************************************************/
501
for(step = 0;step < rang; step ++)
502
{
503
/*******************************************************************\
504
| Search for the minimal entry of M[step][step],...,M[rang][rang]
505
| and swap it to M[step][step]
506
\*******************************************************************/
507
j = step;
508
for(i=step+1; i<rang;i++)
509
{
510
if(mpz_cmp(&M[i][i], &M[j][j]) < 0)
511
j = i;
512
}
513
if(j != step)
514
{
515
mpz_set(&merk, &M[step][step]);
516
mpz_set(&M[step][step], &M[j][j]);
517
mpz_set(&M[j][j], &merk);
518
if(t_option != 0)
519
{
520
merkpointer = trf[step];
521
trf[step] = trf[j];
522
trf[j] = merkpointer;
523
}
524
525
/* inserted following 6 lines: oliver 30/4/1999 */
526
if(r_t_option != 0)
527
{
528
for(m=0;m<cols;m++)
529
{
530
mpz_set(&merk, &rtrf[m][step]);
531
mpz_set(&rtrf[m][step], &rtrf[m][j]);
532
mpz_set(&rtrf[m][j], &merk);
533
}
534
}
535
}
536
for(i=step+1;i<rang;i++)
537
{
538
mpz_mod(&merk, &M[i][i], &M[step][step]);
539
540
/*changed the following if else: 2/3/1999 oliver */
541
if(mpz_cmp_si(&merk, 0) != 0)
542
{
543
if(t_option == TRUE || r_t_option == TRUE)
544
{
545
mpz_gcdext(&g, &a1, &a2, &M[step][step], &M[i][i]);
546
if(t_option == TRUE)
547
{
548
for(j=0;j<rows;j++)
549
mpz_add(&trf[step][j], &trf[step][j], &trf[i][j]);
550
551
mpz_div(&f, &M[i][i], &g);
552
mpz_mul(&f, &f, &a2);
553
for(j=0;j<rows;j++)
554
{
555
mpz_mul(&merk, &f, &trf[step][j]);
556
mpz_sub(&trf[i][j], &trf[i][j], &merk);
557
}
558
559
}
560
if(r_t_option == TRUE)
561
{
562
if((help = (MP_INT *)malloc(cols *sizeof(MP_INT))) == NULL)
563
{
564
printf("malloc of 'help' in 'long_elt_mat' failed\n");
565
exit(2);
566
}
567
for(j=0;j<cols;j++)
568
{
569
mpz_init_set(&help[j], &rtrf[j][step]);
570
mpz_mul(&rtrf[j][step],&rtrf[j][step],&a1);
571
mpz_mul(&merk, &rtrf[j][i], &a2);
572
mpz_add(&rtrf[j][step], &rtrf[j][step], &merk);
573
}
574
mpz_div(&o, &M[step][step], &g );
575
mpz_div(&f, &M[i][i], &g);
576
for(j=0;j<cols;j++)
577
{
578
mpz_mul(&merk, &f, &help[j]);
579
mpz_clear(&help[j]);
580
mpz_mul(&rtrf[j][i], &rtrf[j][i], &o);
581
mpz_sub(&rtrf[j][i], &rtrf[j][i], &merk);
582
}
583
free(help);
584
}
585
mpz_div(&merk, &M[i][i], &g);
586
mpz_mul(&M[i][i], &merk, &M[step][step]);
587
588
/* changed 28/2/97 tilman from
589
mpz_div(&M[step][step], &M[step][step], &g);
590
to: */
591
mpz_set(&M[step][step],&g);
592
}
593
else
594
{
595
mpz_gcd(&g, &M[step][step], &M[i][i]);
596
mpz_div(&merk, &M[i][i], &g);
597
mpz_mul(&M[i][i], &merk, &M[step][step]);
598
599
/* changed 28/2/97 tilman from
600
mpz_div(&M[step][step], &M[step][step], &g);
601
to: */
602
mpz_set(&M[step][step],&g);
603
}
604
}
605
}
606
}
607
608
if (0) dump_MP_mat(NULL,0,0,NULL);
609
610
erg = MP_mat_to_matrix(M, rows, cols);
611
612
if(t_option == TRUE)
613
{
614
for(i=0;i<rows;i++)
615
for(j=0;j<rows;j++)
616
{
617
if(abs(trf[i][j]._mp_size) > 1)
618
{
619
printf("Error: Integer overflow in 'long_mat_elt'\n");
620
exit(3);
621
}
622
left_trans->array.SZ[i][j] = mpz_get_si(&trf[i][j]);
623
}
624
}
625
/* inserted following "if": oliver 2/3/1999 */
626
if(r_t_option == TRUE)
627
{
628
for(i=0;i<cols;i++)
629
{
630
for(j=0;j<cols;j++)
631
{
632
if(abs(rtrf[i][j]._mp_size) > 1)
633
{
634
printf("Error: Integer overflow in 'long_mat_elt'\n");
635
exit(3);
636
}
637
right_trans->array.SZ[i][j] = mpz_get_si(&rtrf[i][j]);
638
mpz_clear(&rtrf[i][j]);
639
}
640
free(rtrf[i]);
641
}
642
}
643
644
for(i=0;i<rows;i++)
645
{
646
if(t_option == TRUE)
647
{
648
for(j=0;j<rows;j++)
649
mpz_clear(&trf[i][j]);
650
free(trf[i]);
651
}
652
for(j=0;j<cols;j++)
653
mpz_clear(&M[i][j]);
654
free(M[i]);
655
}
656
free(M);
657
if(t_option == TRUE)
658
free(trf);
659
if(r_t_option == TRUE)
660
free(rtrf);
661
merkpointer = NULL;
662
mpz_clear(&a1), mpz_clear(&a2);
663
mpz_clear(&x1), mpz_clear(&x2);
664
mpz_clear(&y1), mpz_clear(&y2);
665
mpz_clear(&f), mpz_clear(&g); mpz_clear(&o);
666
mpz_clear(&merk); mpz_clear(&pos1); mpz_clear(&pos2);
667
Check_mat(erg);
668
if(t_option == TRUE)
669
Check_mat(left_trans);
670
if(r_t_option == TRUE)
671
Check_mat(right_trans);
672
673
/*inserted next 2 lines: oliver 16/3/99 */
674
erg->kgv = Mat->kgv;
675
Check_mat(erg);
676
677
678
return(erg);
679
}
680
681
682