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

563580 views
1
#include "typedef.h"
2
#include "matrix.h"
3
#include "tools.h"
4
/**************************************************************************\
5
@---------------------------------------------------------------------------
6
@---------------------------------------------------------------------------
7
@ FILE: elt_div_mat.c
8
@---------------------------------------------------------------------------
9
@---------------------------------------------------------------------------
10
@
11
\**************************************************************************/
12
13
/*{{{}}}*/
14
/*{{{ local typedefs*/
15
/*
16
* local typedefs, only used in this file.
17
*/
18
typedef struct
19
{
20
int f1, f2, g1, g2;
21
} elt_div_pair;
22
typedef struct
23
{
24
int low, hi;
25
} elt_div_prod;
26
27
/*}}} */
28
/*{{{ mindivmod, static*/
29
/*============================================================*\
30
|| ||
31
|| Loest azahl = prod.hi * bzahl + prod.low mit (meistens) ||
32
|| prod.low <= bzahl/2 ||
33
|| ||
34
\*============================================================*/
35
36
elt_div_prod ZZ_mindivmod(azahl,bzahl)
37
int azahl,bzahl;
38
{
39
elt_div_prod c;
40
int q_signum, r_signum;
41
42
c.hi = c.low = 0;
43
r_signum = azahl ? ( azahl > 0 ? 1 : -1 ) : 0;
44
q_signum = bzahl ? ( bzahl > 0 ? 1 : -1 ) : 0;
45
q_signum = r_signum == q_signum ? 1 : -1;
46
47
azahl= abs(azahl);
48
bzahl= abs(bzahl);
49
c.hi = azahl / bzahl;
50
c.low= azahl % bzahl;
51
if ( (c.low * 2 ) > bzahl ) {
52
c.hi++;
53
c.low = bzahl - c.low;
54
r_signum *= -1;
55
}
56
c.hi *= q_signum;
57
c.low *= r_signum;
58
return(c);
59
}
60
61
/*}}} */
62
/*{{{ euclid, static*/
63
/*
64
*
65
* static elt_div_pair euclid(a,b);
66
*
67
* /a\ /ggt(a,b)\
68
* berechnet Matrix A so, dass A * | | = | |
69
* \b/ \ 0 /
70
*
71
*/
72
static elt_div_pair euclid(a,b) /* frei nach gap */
73
int a,b;
74
{
75
elt_div_pair r;
76
elt_div_prod temp;
77
int s1, t1, s, t, q, d, ha, hb;
78
79
temp.hi =
80
temp.low =
81
ha =
82
hb =
83
s1 =
84
t =
85
q =
86
d =
87
r.f1 =
88
r.f2 =
89
r.g1 =
90
r.g2 = 0;
91
t1 =
92
s = 1;
93
if (a < 0) {
94
s = -1;
95
}
96
hb= abs(b);
97
ha= abs(a);
98
while (hb != 0) {
99
temp = ZZ_mindivmod(ha,hb);
100
q = temp.hi;
101
temp.hi = 0;
102
ha = hb;
103
hb = temp.low;
104
temp.low = 0;
105
t1 = t;
106
t = -t*q + s;
107
s = t1;
108
}
109
r.g1 = t;
110
r.f1 = s;
111
s = ha - s * a;
112
r.f2 = s/b;
113
t *= a;
114
r.g2 = - t/b;
115
return r;
116
}
117
118
/*}}} */
119
120
/*{{{ elt_func, static*/
121
static matrix_TYP *elt_func ( mat )
122
matrix_TYP *mat;
123
{
124
int min_sum, sum,**E, h,*v, _min_;
125
int min_col, min_row, rM, cM, i, j, k,l;
126
boolean rc_min, flag, Global_flag;
127
#ifdef DEBUG
128
char *temp = "tempA";
129
#endif
130
matrix_TYP *elt;
131
elt_div_pair paar;
132
133
Global_flag = FALSE;
134
135
if ( !(mat->flags.Integral & 1)) {
136
fprintf (stderr, "Elementary divisors of a rational matrix ??\n");
137
exit (3);
138
}
139
/*------------------------------------------------------------*\
140
| Copy mat->array.SZ into E |
141
\*------------------------------------------------------------*/
142
rM = mat->rows;
143
cM = mat->cols;
144
h =
145
_min_ =
146
min_sum =
147
sum = 0;
148
elt = copy_mat(mat);
149
E = elt->array.SZ;
150
rc_min = TRUE;
151
for ( i = 0; i < cM; i++) {
152
#ifdef DEBUG
153
if (Global_flag)
154
put_mat(elt,temp,NULL,0);
155
temp[4]++;
156
#endif
157
/*---------------------------------------------------------*\
158
| Extended Version: Try to decrease the entries of the |
159
| matrix by using linear combinations of rows and columns |
160
\*---------------------------------------------------------*/
161
if (E[i][i] != 0) {
162
for(j = i+1; j < rM; j++) {
163
if((h= min_div(E[j][i],E[i][i])) != 0) {
164
if( h == 1 ) {
165
for(k = i; k < cM; k++) {
166
if (E[i][k] != 0) {
167
E[j][k] -= E[i][k];
168
}
169
}
170
} else if (h == -1) {
171
for(k = i; k < cM; k++) {
172
if (E[i][k] != 0) {
173
E[j][k] += E[i][k];
174
}
175
}
176
} else {
177
for(k = i; k < cM; k++) {
178
if (E[i][k] != 0) {
179
E[j][k] -= h*E[i][k];
180
}
181
}
182
}
183
}
184
}
185
for(j = i+1; j < cM; j++) {
186
if((h= min_div(E[i][j],E[i][i])) != 0) {
187
if(h == 1) {
188
for(k = i; k < rM; k++) {
189
if (E[k][i] != 0) {
190
E[k][j] -= E[k][i];
191
}
192
}
193
} else if (h == -1) {
194
for(k = i; k < rM; k++) {
195
if (E[k][i] != 0) {
196
E[k][j] += E[k][i];
197
}
198
}
199
} else {
200
for(k = i; k < rM; k++) {
201
if (E[k][i] != 0) {
202
E[k][j] -= h*E[k][i];
203
}
204
}
205
}
206
}
207
}
208
}
209
/* put_mat(elt,NULL,NULL,0); */
210
/*{{{ */
211
/*----------------------------------------------------------*\
212
| Second extension: Trying to decrease the Entries of the |
213
| matrix by using a modificated pair Reduction. |
214
| (But it seems to make it slower in some cases)
215
\*----------------------------------------------------------
216
if ((i%3) == 0) {
217
for(l = i+1; (l < rM) && (l < cM); l++) {
218
if(E[l][l] != 0) {
219
for(j = i+1; j < rM; j++)
220
if(j != l) {
221
if((h= min_div(E[j][l],E[l][l])) != 0) {
222
if(h == 1)
223
for(k = i; k < cM; k++) {
224
if (E[l][k] != 0) E[j][k] -= E[l][k];
225
}
226
else if (h == MINUS_1)
227
for(k = i; k < cM; k++) {
228
if (E[l][k] != 0) E[j][k] += E[l][k];
229
}
230
else
231
for(k = i; k < cM; k++) {
232
if (E[l][k] != 0) E[j][k] -= h*E[l][k];
233
}
234
}
235
}
236
for(j = i+1; j < cM; j++)
237
if(j != l) {
238
if((h= min_div(E[l][j],E[l][l])) != 0) {
239
if(h == 1)
240
for(k = i; k < rM; k++) {
241
if (E[k][l] != 0) E[k][j] -= E[k][l];
242
}
243
else if (h == MINUS_1)
244
for(k = i; k < rM; k++) {
245
if (E[k][l] != 0) E[k][j] += E[k][l];
246
}
247
else
248
for(k = i; k < rM; k++) {
249
if (E[k][l] != 0) E[k][j] -= h*E[k][l];
250
}
251
}
252
}
253
}
254
}
255
put_mat(elt,NULL,NULL,2);
256
}*/
257
/*}}} */
258
/*---------------------------------------------------------*\
259
| Find the minimum of all abs. values of non-zero entries |
260
| in the remaining (rM - i)-dimensional lower right |
261
| submatrix |
262
\*---------------------------------------------------------*/
263
264
flag = TRUE;
265
min_row = min_col = i;
266
_min_ = 0;
267
for ( j = i; (j < rM); j++ ) {
268
for (k = i; (k < cM); k++) {
269
if ( E[j][k] != 0 ) {
270
if (_min_ == 0) {
271
_min_= abs(E[j][k]);
272
min_row = j;
273
min_col = k;
274
if (rc_min) {
275
min_sum = 0;
276
for(l = i; l < rM; l++) {
277
if (E[l][k] < 0) {
278
min_sum -= E[l][k];
279
} else {
280
min_sum += E[l][k];
281
}
282
}
283
}
284
} else {
285
flag = abs(E[j][k]) == abs(_min_) ? 0 : (abs(E[j][k]) < abs(_min_) ? -1 : 1 );
286
if ( flag == -1 ) {
287
_min_= abs(E[j][k]);
288
if ((rc_min) && (k != min_col)) {
289
min_sum = 0;
290
for(l = i; l < rM; l++) {
291
if (E[l][k] < 0) {
292
min_sum -= E[l][k];
293
} else {
294
min_sum += E[l][k];
295
}
296
}
297
}
298
min_row = j;
299
min_col = k;
300
} else if((rc_min) && (flag == 0) && (k!= min_col)) {
301
sum = 0;
302
for(l = i; l < rM; l++) {
303
if (E[l][k] < 0) {
304
sum -= E[l][k];
305
} else {
306
sum += E[l][k];
307
}
308
}
309
if(sum < min_sum) {
310
min_row = j;
311
min_col = k;
312
min_sum = sum;
313
sum = 0;
314
}
315
}
316
}
317
}
318
}
319
}
320
if( _min_ == 0) {
321
goto ende;
322
}
323
if( _min_ == 1) {
324
flag = FALSE;
325
} else {
326
flag = TRUE;
327
}
328
rc_min = TRUE; /* (min & 0); */
329
330
/*---------------------------------------------------------*\
331
| Swap the min-entry into upper left corner |
332
\*---------------------------------------------------------*/
333
v = E[i];
334
E[i] = E[min_row];
335
E[min_row] = v;
336
for ( j = i; j < rM; j++ ) {
337
h = E[j][i];
338
E[j][i] = E[j][min_col];
339
E[j][min_col] = h;
340
}
341
h = 0;
342
343
/*------------------------------------------------------*\
344
| try to decrease the min using linear combinations |
345
| of rows |
346
\*------------------------------------------------------*/
347
marke:
348
if ( flag ) {
349
for(j = rM-1; flag && (j > i); j--) {
350
if ( (h = E[j][i]%_min_) != 0 ) {
351
paar = euclid (E[i][i], E[j][i]);
352
/* find differences for momo
353
sprintf(comment,"%d %d", i,j);
354
put_mat(elt,NULL,comment,0); */
355
356
for ( k = i; k < cM ; k++) {
357
h += E[i][k]*paar.f1+E[j][k]*paar.f2;
358
E[j][k]= E[j][k]*paar.g2+E[i][k]*paar.g1;
359
E[i][k] = h;
360
}
361
if ( (_min_= abs(E[i][i])) == 1 ) {
362
flag = FALSE;
363
}
364
}
365
}
366
}
367
if ( flag ) {
368
/*------------------------------------------------------*\
369
| try to decrease the min using linear combinations |
370
| of columns |
371
\*------------------------------------------------------*/
372
for ( j = cM-1; j > i; j--) {
373
if ( (h= E[i][j]%_min_) != 0 ) {
374
paar = euclid (E[i][i], E[i][j]);
375
for ( k = i; k < rM; k++) {
376
h += E[k][i]*paar.f1+E[k][j]*paar.f2;
377
E[k][j] = E[k][j]*paar.g2 + E[k][i]*paar.g1;
378
E[k][i] = h;
379
}
380
if ( (_min_ = abs(E[i][i])) == 1 ) {
381
flag = FALSE;
382
}
383
}
384
}
385
}
386
/*---------------------------------------------------------*\
387
| Clear the i-th column |
388
\*---------------------------------------------------------*/
389
for(j = i+1; j < rM ; j++ ) {
390
h=E[j][i]/E[i][i];
391
if (h != 0) {
392
for ( k = i; k < cM ; k++ ) {
393
if(E[i][k] != 0) {
394
E[j][k] -= h*E[i][k];
395
}
396
}
397
}
398
if(E[j][i] != 0) {
399
goto marke;
400
}
401
}
402
/*---------------------------------------------------------*\
403
| Clear the i-th row |
404
\*---------------------------------------------------------*/
405
E[i][i] = abs(E[i][i]);
406
for (j = i+1; j < cM; j++) {
407
E[i][j] = 0;
408
}
409
}
410
ende:
411
for (i = 1; i < elt->cols; i++) {
412
if ( (E[i][i] % E[i-1][i-1]) != 0 ) {
413
h= E[i-1][i-1];
414
E[i-1][i-1]= GGT( E[i][i], h);
415
h /= E[i-1][i-1];
416
E[i][i] *= h;
417
if (i > 1) {
418
i -= 2;
419
}
420
}
421
}
422
for (i = 0; i < elt->cols; i++) {
423
if ( E[i][i] < 0 ) {
424
E[i][i] = -E[i][i];
425
}
426
}
427
428
for (i = 1; i < elt->cols; i++) {
429
elt->array.SZ[0][i] = elt->array.SZ[i][i];
430
}
431
for (i = 1; i < elt->rows; i++) {
432
free(elt->array.SZ[i]);
433
if( elt->array.N != NULL ) {
434
free(elt->array.N[i]);
435
}
436
}
437
elt->rows = 1;
438
Check_mat(elt);
439
return (elt);
440
}
441
442
/*}}} */
443
/*{{{ elt_div*/
444
/*
445
@-----------------------------------------------------------------
446
@ matrix_TYP *elt_div(Mat)
447
@ matrix_TYP *Mat;
448
@
449
@ computes elementary divisors of Mat.
450
@ Result is a matrix with a single row that contains the
451
@ divisors.
452
@-----------------------------------------------------------------
453
*/
454
matrix_TYP *elt_div(Mat)
455
matrix_TYP *Mat;
456
{
457
matrix_TYP *Elt, *tmp;
458
459
if(null_mat(Mat)) {
460
Elt = init_mat(1,1,"0");
461
return(Elt);
462
}
463
464
if (Mat->rows >= Mat->cols) {
465
Elt = ggauss(Mat);
466
tmp = tr_pose(Elt);
467
free_mat(Elt);
468
tgauss(tmp);
469
} else {
470
tmp = tr_pose(Mat);
471
Elt = ggauss(tmp);
472
free_mat(tmp);
473
tmp = tr_pose(Elt);
474
free_mat(Elt);
475
tgauss(tmp);
476
}
477
Elt = elt_func(tmp);
478
free_mat(tmp);
479
return(Elt);
480
}
481
/*}}} */
482
483