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

563680 views
1
#include "typedef.h"
2
#include "tools.h"
3
#include "matrix.h"
4
5
/**************************************************************************\
6
@---------------------------------------------------------------------------
7
@---------------------------------------------------------------------------
8
@ FILE: tools_mat.c
9
@---------------------------------------------------------------------------
10
@---------------------------------------------------------------------------
11
@
12
\**************************************************************************/
13
/*{{{}}}*/
14
/*{{{ iset_entry*/
15
/*
16
@---------------------------------------------------------------------
17
@ boolean iset_entry(mat, r, c, v);
18
@ matrix_TYP *mat;
19
@ int r,c;
20
@ int v;
21
@
22
@ Set an integer entry in the r-th row and c-th column of mat to v.
23
@
24
@-------------------------------------------------------------------------
25
*/
26
27
boolean iset_entry(mat, r, c, v)
28
matrix_TYP *mat;
29
int r,c;
30
int v;
31
{
32
int w;
33
34
/*
35
* Check rows and columns
36
*/
37
if((r >= mat->rows) || (c >= mat->cols)) {
38
fprintf(stderr,"Error: Limits of coordinates violated \n");
39
return(FALSE);
40
}
41
42
if( mat->prime != 0 ) {
43
if((w = v % mat->prime) < 0) {
44
w += mat->prime;
45
}
46
mat->array.SZ[r][c] = w;
47
} else if(mat->flags.Integral) {
48
mat->array.SZ[r][c] = v;
49
} else {
50
mat->array.SZ[r][c] = v*mat->kgv;
51
}
52
if(mat->flags.Symmetric && (r != c)) { /* Check matrix flags */
53
mat->flags.Symmetric = FALSE;
54
Check_mat(mat);
55
}
56
return(TRUE);
57
}
58
59
/*}}} */
60
/*{{{ rset_entry*/
61
62
/*
63
@-------------------------------------------------------------------------
64
@
65
@ boolean rset_entry(mat, r, c, v);
66
@ matrix_TYP *mat;
67
@ int r, c;
68
@ rational v;
69
@
70
@ Set an rational entry in the r-th row and c-th column of mat to v
71
@
72
@-------------------------------------------------------------------------
73
*/
74
boolean rset_entry(mat, r, c, v)
75
matrix_TYP *mat;
76
int r, c;
77
rational v;
78
{
79
int t, t1, t2;
80
int **Z;
81
int w;
82
int i,j;
83
84
if(v.n == 1) { /* rational is actually an integer */
85
return(iset_entry(mat,r,c,v.z));
86
}
87
88
t = t1 = t2 = 0;
89
/* Check rows and columns */
90
if((r >= mat->rows) || (c >= mat->cols)) {
91
fprintf(stderr,"Error: Limits of coordinates violated \n");
92
return(FALSE);
93
}
94
95
if( mat->prime != 0 ) { /* somehow pathologic, but why not */
96
w= (v.z%v.n)%mat->prime;
97
mat->array.SZ[r][c] = w;
98
} else {
99
t= GGT(mat->kgv,v.n);
100
if(t == v.n) {
101
t1= v.z*mat->kgv/t;
102
mat->array.SZ[r][c] = t1;
103
} else {
104
t1= v.n/t;
105
mat->kgv *= t1;
106
Z = mat->array.SZ;
107
for(i = 0; i < mat->rows; i++) {
108
for(j = 0; j < mat->cols; j++) {
109
Z[i][j] *= t1;
110
}
111
}
112
Z[r][c]= v.z*mat->kgv/t;
113
}
114
}
115
116
if(mat->flags.Symmetric && (r != c)) { /* Check matrix flags */
117
mat->flags.Symmetric = FALSE;
118
Check_mat(mat);
119
}
120
return(TRUE);
121
}
122
/*}}} */
123
/*{{{ iscal_mul*/
124
/*
125
@-------------------------------------------------------------------------
126
@
127
@ void iscal_mul(mat, v);
128
@ matrix_TYP *mat;
129
@ int v;
130
@
131
@ Multiply matrix with integer scalar
132
@
133
@-------------------------------------------------------------------------
134
*/
135
void iscal_mul(mat, v)
136
matrix_TYP *mat;
137
int v;
138
{
139
int i,j;
140
int **Z;
141
int t;
142
143
/* handle the trivial cases */
144
if (v == 1) {
145
return;
146
}
147
if ( null_mat( mat ) ) {
148
return;
149
}
150
if (v == 0) {
151
t = 0;
152
memset2dim( (char **)mat->array.SZ, mat->rows, mat->cols, sizeof(int), (char *)&t );
153
Check_mat(mat);
154
return;
155
}
156
157
t= mat->kgv%v;
158
if ( (mat->prime == 0) && (t == 0)) {
159
mat->kgv /= v;
160
if(mat->kgv == 1 || mat->kgv == -1 ) { /* take care of negative values */
161
mat->flags.Integral = TRUE;
162
if(mat->kgv == -1) {
163
mat->kgv = 1;
164
Z = mat->array.SZ;
165
if(mat->flags.Diagonal) {
166
for(i = 0; i < mat->rows; i++) {
167
Z[i][i] = -Z[i][i];
168
}
169
} else {
170
for(i = 0; i < mat->rows; i++) {
171
for(j = 0; j < mat->cols; j++) {
172
Z[i][j] = -Z[i][j];
173
}
174
}
175
}
176
}
177
}
178
return;
179
}
180
181
/* now the real work */
182
Z = mat->array.SZ;
183
if( mat->prime != 0 ) {
184
if((v %= mat->prime) < 0) {
185
v += mat->prime;
186
}
187
init_prime(mat->prime);
188
if(mat->flags.Diagonal) {
189
for(i = 0; i < mat->rows; i++) {
190
Z[i][i] = P(Z[i][i],v);
191
}
192
} else {
193
for(i = 0; i < mat->rows; i++) {
194
for(j = 0; j < mat->cols; j++) {
195
Z[i][j] = P(Z[i][j],v);
196
}
197
}
198
}
199
} else { /* P_TYP */
200
t= GGT(mat->kgv,v);
201
if( t != 1 ) {
202
mat->kgv /= t;
203
v /= t;
204
}
205
if(mat->flags.Diagonal) {
206
for(i = 0; i < mat->rows; i++) {
207
Z[i][i] *= v;
208
}
209
} else {
210
for(i = 0; i < mat->rows; i++) {
211
for(j = 0; j < mat->cols; j++) {
212
Z[i][j] *= v;
213
}
214
}
215
}
216
}
217
}
218
219
/*}}} */
220
/*{{{ rscal_mul*/
221
/*
222
@-------------------------------------------------------------------------
223
@
224
@ void rscal_mul(mat,v);
225
@ matrix_TYP *mat;
226
@ rational v;
227
@
228
@ Multiply matrix with rational scalar
229
@
230
@-------------------------------------------------------------------------
231
*/
232
void rscal_mul(mat,v)
233
matrix_TYP *mat;
234
rational v;
235
{
236
int vz, t;
237
int pp;
238
239
if( null_mat( mat ) ) {
240
return;
241
}
242
if(v.z == 0) {
243
t = 0;
244
memset2dim( (char **)mat->array.SZ, mat->rows, mat->cols, sizeof(int), (char *)&t );
245
Check_mat(mat);
246
return;
247
}
248
vz =
249
t = 0;
250
Normal(&v);
251
if(v.n == 1) {
252
iscal_mul(mat, v.z);
253
return;
254
}
255
256
if(mat->prime != 0) {
257
init_prime(mat->prime);
258
vz= v.z%mat->prime;
259
t = v.n%mat->prime;
260
pp = P(vz, t);
261
iscal_mul(mat,pp);
262
}
263
if(mat->flags.Integral) {
264
mat->kgv= v.n;
265
mat->flags.Integral = FALSE;
266
vz= v.z;
267
} else {
268
t= GGT(mat->kgv,v.z);
269
mat->kgv= mat->kgv/t*v.n;
270
vz= v.z/t;
271
}
272
273
if(v.z == 1) {
274
Check_mat(mat);
275
} else {
276
iscal_mul(mat,vz);
277
}
278
}
279
/*}}} */
280
/*{{{ kill_row*/
281
/*
282
@-------------------------------------------------------------------------
283
@
284
@ boolean kill_row(mat, row);
285
@ matrix_TYP *mat;
286
@ int row;
287
@
288
@ Kill one row in the matrix
289
@ The argument 'row' must use the indexing of the matrix, ie.
290
@ the rows are numbered from 0 to n-1.
291
@
292
@-------------------------------------------------------------------------
293
*/
294
boolean kill_row(mat, row)
295
matrix_TYP *mat;
296
int row;
297
{
298
int i;
299
int **Z;
300
301
if(row >= mat->rows) {
302
fprintf(stderr,"Error in kill_row: not so many rows!\n");
303
return(FALSE);
304
}
305
306
Z = mat->array.SZ;
307
free( Z[row] );
308
for(i = row+1; i < mat->rows; i++) {
309
Z[i-1] = Z[i];
310
}
311
mat->rows--;
312
mat->array.SZ = (int **)realloc(Z,mat->rows*sizeof(int *));
313
314
if( mat->array.N != NULL ) {
315
Z = mat->array.N;
316
free(Z[row]);
317
for(i = row+1; i < mat->rows+1; i++) {
318
Z[i-1] = Z[i];
319
}
320
mat->array.N = (int **)realloc(Z,mat->rows*sizeof(int *));
321
}
322
mat->flags.Symmetric = FALSE;
323
Check_mat(mat);
324
return(TRUE);
325
}
326
/*}}} */
327
/*{{{ kill_col*/
328
/*
329
@-------------------------------------------------------------------------
330
@
331
@ boolean kill_col(mat, col);
332
@ matrix_TYP *mat;
333
@ int col;
334
@
335
@ Kill one column in the matrix
336
@ The argument 'col' must use the indexing of the matrix, ie.
337
@ the cols are numbered from 0 to n-1.
338
@
339
@-------------------------------------------------------------------------
340
*/
341
boolean kill_col(mat, col)
342
matrix_TYP *mat;
343
int col;
344
{
345
int i, j;
346
int **Z;
347
348
if(col >= mat->cols) {
349
fprintf(stderr,"Error in kill_col: not so many cols!\n");
350
return(FALSE);
351
}
352
353
Z = mat->array.SZ;
354
for(i = 0; i < mat->rows; i++) {
355
for(j = col; j < mat->cols; j++) {
356
Z[i][j] = Z[i][j+1];
357
}
358
Z[i] = (int *)realloc(Z[i], (mat->cols-1)*sizeof(int *));
359
}
360
361
if( mat->array.N != NULL) {
362
Z = mat->array.N;
363
for(i = 0; i < mat->rows; i++) {
364
for(j = col; j < mat->cols; j++) {
365
Z[i][j] = Z[i][j+1];
366
}
367
Z[i] = (int *)realloc(Z[i], (mat->cols-1)*sizeof(int *));
368
}
369
}
370
371
mat->cols--;
372
mat->flags.Symmetric = FALSE;
373
Check_mat(mat);
374
return(TRUE);
375
}
376
377
/*}}} */
378
/*{{{ ins_row*/
379
/*
380
@-------------------------------------------------------------------------
381
@ boolean ins_row(mat, row);
382
@ matrix_TYP *mat;
383
@ int row;
384
@
385
@ Insert one row in the matrix
386
@ The argument 'row' must use the indexing of the matrix, ie.
387
@ the rows are numbered from 0 to n-1.
388
@
389
@-------------------------------------------------------------------------
390
*/
391
boolean ins_row(mat, row)
392
matrix_TYP *mat;
393
int row;
394
{
395
int i;
396
int **Z;
397
398
if(row > mat->rows) {
399
fprintf(stderr,"Error in ins_row: not so many rows!\n");
400
return(FALSE);
401
}
402
403
mat->rows++;
404
Z=(int **)realloc(mat->array.SZ,mat->rows*sizeof(int *));
405
mat->array.SZ = Z;
406
for(i = mat->rows-1; i > row; i--) {
407
Z[i] = Z[i-1];
408
}
409
Z[row] = (int *)calloc(mat->cols , sizeof(int ));
410
411
if( mat->array.N) {
412
Z=(int **)realloc(mat->array.N,mat->rows*sizeof(int *));
413
mat->array.N = Z;
414
for(i = mat->rows-1; i > row; i--) {
415
Z[i] = Z[i-1];
416
}
417
Z[row] = (int *)calloc(mat->cols , sizeof(int ));
418
}
419
420
Check_mat(mat);
421
return(TRUE);
422
}
423
/*}}} */
424
/*{{{ ins_col*/
425
/*
426
@-------------------------------------------------------------------------
427
@ boolean ins_col(mat, col);
428
@ matrix_TYP *mat;
429
@ int col;
430
@
431
@ Insert one column in the matrix
432
@ The argument 'col' must use the indexing of the matrix, ie.
433
@ the cols are numbered from 0 to n-1.
434
@
435
@-------------------------------------------------------------------------
436
*/
437
438
boolean ins_col(mat, col)
439
matrix_TYP *mat;
440
int col;
441
{
442
int i, j;
443
int **Z;
444
445
if(col > mat->cols) {
446
fprintf(stderr,"Error in kill_col: not so many cols!\n");
447
return(FALSE);
448
}
449
450
mat->cols++;
451
452
Z = mat->array.SZ;
453
for(i = 0; i < mat->rows; i++) {
454
Z[i] = (int *)realloc(Z[i], mat->cols*sizeof(int));
455
for(j = mat->cols-1; j > col; j--) {
456
Z[i][j] = Z[i][j-1];
457
}
458
Z[i][col] = 0;
459
}
460
if( mat->array.N != NULL) {
461
Z = mat->array.N;
462
for(i = 0; i < mat->rows; i++) {
463
Z[i] = (int *)realloc(Z[i], mat->cols*sizeof(int));
464
for(j = mat->cols-1; j > col; j--) {
465
Z[i][j] = Z[i][j-1];
466
}
467
Z[i][col] = 0;
468
}
469
}
470
471
Check_mat(mat);
472
return(TRUE);
473
}
474
/*}}} */
475
/*{{{ imul_row*/
476
/*
477
@-------------------------------------------------------------------------
478
@ boolean imul_row(mat, row, v);
479
@ matrix_TYP *mat;
480
@ int row, v;
481
@
482
@ Multiply row with an integer
483
@
484
@-------------------------------------------------------------------------
485
*/
486
boolean imul_row(mat, row, v)
487
matrix_TYP *mat;
488
int row, v;
489
{
490
int j;
491
int **Z;
492
493
if(row >= mat->rows) {
494
fprintf(stderr,"Error in imul_row: not so many rows!\n");
495
return(FALSE);
496
}
497
/* handle the trivial cases */
498
if (v == 1) {
499
return(TRUE);
500
}
501
if ( null_mat( mat ) ) {
502
return(TRUE);
503
}
504
if (v == 0) {
505
memset( mat->array.SZ[row], '\0', sizeof(int)*mat->cols );
506
Check_mat(mat);
507
return(TRUE);
508
}
509
Z = mat->array.SZ;
510
if( mat->prime != 0) {
511
if( (v %= mat->prime) < 0 ) {
512
v += mat->prime;
513
}
514
if(v == 1) {
515
return(TRUE);
516
}
517
init_prime(mat->prime);
518
if(mat->flags.Diagonal) {
519
Z[row][row] = P(Z[row][row],v);
520
} else {
521
for(j = 0; j < mat->cols; j++) {
522
Z[row][j] = P(Z[row][j],v);
523
}
524
}
525
} else { /* flags & P_TYP */
526
if(mat->flags.Diagonal) {
527
Z[row][row] *= v;
528
} else {
529
for(j = 0; j < mat->cols; j++) {
530
Z[row][j] *= v;
531
}
532
}
533
}
534
535
if(!(mat->flags.Diagonal)) {
536
mat->flags.Symmetric = FALSE;
537
}
538
Check_mat(mat);
539
return(TRUE);
540
}
541
542
/*}}} */
543
/*{{{ rmul_row*/
544
/*
545
@-------------------------------------------------------------------------
546
@ boolean rmul_row(mat, row, v);
547
@ matrix_TYP *mat;
548
@ int row;
549
@ rational v;
550
@
551
@ Multiply row with a rational
552
@
553
@-------------------------------------------------------------------------
554
*/
555
boolean rmul_row(mat, row, v)
556
matrix_TYP *mat;
557
int row;
558
rational v;
559
{
560
int i,j;
561
int waste, t;
562
int **Z;
563
564
if(row >= mat->rows) {
565
fprintf(stderr,"Error in rmul_row: not so many rows!\n");
566
return(FALSE);
567
}
568
if( mat->prime != 0 ) {
569
t= (v.z%v.n)%mat->prime;
570
/* modeq(mod(&t,v.z,v.n),int_to_lang(mat->prime)); */
571
return(imul_row(mat,row,t));
572
}
573
imul_row(mat,row,v.z);
574
if(v.n == 1) {
575
return(TRUE);
576
}
577
578
waste = t = 0;
579
580
Z = mat->array.SZ;
581
if(mat->flags.Diagonal) {
582
if(Z[row][row] == 0) {
583
return(TRUE);
584
}
585
t= GGT(Z[row][row], v.n);
586
if(t == v.n) {
587
Z[row][row] /= v.n;
588
return(TRUE);
589
} else {
590
waste= v.n/t;
591
Z[row][row] /= t;
592
mat->kgv *= waste;
593
for(i = 0; i < row; i++) {
594
Z[i][i] *= waste;
595
}
596
for(i = row+1; i < mat->rows; i++) {
597
Z[i][i] *= waste;
598
}
599
}
600
} else {
601
t= v.n;
602
for(i = 0; i < mat->cols; i++) {
603
if(Z[row][i] != 0) {
604
t= GGT(t,Z[row][i]);
605
if(t == 1) {
606
i = mat->cols;
607
}
608
}
609
}
610
if(t != 1) {
611
for(i = 0; i < mat->cols; i++) {
612
if(Z[row][i] != 0) {
613
Z[row][i] /= t;
614
}
615
}
616
waste= v.n/t;
617
} else {
618
waste= v.n;
619
}
620
if(waste != 1) {
621
mat->kgv *= waste;
622
for(j = 0; j < mat->cols; j++) {
623
for(i = 0; i < row; i++) {
624
if(Z[i][j] != 0) Z[i][j] *= waste;
625
}
626
for(i = row+1; i < mat->rows; i++) {
627
if(Z[i][j] != 0) Z[i][j] *= waste;
628
}
629
}
630
}
631
}
632
633
if(!(mat->flags.Diagonal)) {
634
mat->flags.Symmetric = FALSE;
635
}
636
if(mat->kgv != 1) {
637
mat->flags.Integral = FALSE;
638
}
639
Check_mat(mat);
640
return(TRUE);
641
}
642
/*}}} */
643
/*{{{ imulcol*/
644
/*
645
@-------------------------------------------------------------------------
646
@boolean imul_col(mat, col, v)
647
@ matrix_TYP *mat;
648
@ int col, v;
649
@
650
@ Multiply col with an integer
651
@
652
@-------------------------------------------------------------------------
653
*/
654
boolean imul_col(mat, col, v)
655
matrix_TYP *mat;
656
int col, v;
657
{
658
int j;
659
int **Z;
660
661
if(col >= mat->cols) {
662
fprintf(stderr,"Error in imul_col: not so many cols!\n");
663
return(FALSE);
664
}
665
/* handle the trivial cases */
666
if (v == 1) {
667
return(TRUE);
668
}
669
if ( null_mat( mat ) ) {
670
return(TRUE);
671
}
672
if (v == 0) {
673
memset( mat->array.SZ[col], '\0', sizeof(int)*mat->rows );
674
Check_mat(mat);
675
return(TRUE);
676
}
677
678
Z = mat->array.SZ;
679
if( mat->prime != 0 ) {
680
if((v %= mat->prime) < 0) {
681
v += mat->prime;
682
}
683
if(v == 1) {
684
return(TRUE);
685
}
686
init_prime(mat->prime);
687
if(mat->flags.Diagonal) {
688
Z[col][col] = P(Z[col][col],v);
689
} else {
690
for(j = 0; j < mat->rows; j++) {
691
Z[j][col] = P(Z[j][col],v);
692
}
693
}
694
} else {
695
if(mat->flags.Diagonal) {
696
Z[col][col] *= v;
697
} else {
698
for(j = 0; j < mat->rows; j++) {
699
Z[j][col] *= v;
700
}
701
}
702
}
703
if(!(mat->flags.Diagonal)) {
704
mat->flags.Symmetric = FALSE;
705
}
706
Check_mat(mat);
707
return(TRUE);
708
}
709
710
/*}}} */
711
/*{{{ rmul_col*/
712
/*
713
@-------------------------------------------------------------------------
714
@ boolean rmul_col(mat, col, v);
715
@ matrix_TYP *mat;
716
@ int col;
717
@ rational v;
718
@
719
@ Multiply column with a rational
720
@
721
@-------------------------------------------------------------------------
722
*/
723
boolean rmul_col(mat, col, v)
724
matrix_TYP *mat;
725
int col;
726
rational v;
727
{
728
int i,j;
729
int waste, t;
730
int **Z;
731
732
if(col >= mat->cols) {
733
fprintf(stderr,"Error in rmul_col: not so many cols!\n");
734
return(FALSE);
735
}
736
if( mat->prime != 0 ) {
737
t= (v.z%v.n)%mat->prime;
738
return(imul_col(mat,col,t));
739
}
740
741
imul_col(mat,col,v.z);
742
if(v.n == 1) {
743
return(TRUE);
744
}
745
746
waste = t = 0;
747
748
Z = mat->array.SZ;
749
if(mat->flags.Diagonal) {
750
if(Z[col][col] == 0) {
751
return(TRUE);
752
}
753
t= GGT(Z[col][col], v.n);
754
if(t == v.n) {
755
Z[col][col] /= v.n;
756
return(TRUE);
757
} else {
758
waste= v.n/t;
759
Z[col][col] /= t;
760
mat->kgv *= waste;
761
for(i = 0; i < col; i++) {
762
Z[i][i] *= waste;
763
}
764
for(i = col+1; i < mat->cols; i++) {
765
Z[i][i] *= waste;
766
}
767
}
768
} else {
769
t= v.n;
770
for(i = 0; i < mat->rows; i++) {
771
if(Z[i][col] != 0) {
772
t= GGT(t,Z[i][col]);
773
if(t == 1) {
774
i = mat->cols;
775
}
776
}
777
}
778
if(t != 1) {
779
for(i = 0; i < mat->rows; i++) {
780
if(Z[i][col] != 0) {
781
Z[i][col] /= t;
782
}
783
}
784
waste= v.n/t;
785
} else {
786
waste= v.n;
787
}
788
if(waste != 1) {
789
for(i = 0; i < mat->rows; i++) {
790
if(Z[i][col] != 0) {
791
Z[i][col] /= waste;
792
}
793
}
794
mat->kgv *= waste;
795
for(j = 0; j < mat->rows; j++) {
796
for(i = 0; i < col; i++) {
797
Z[j][i] *= waste;
798
}
799
for(i = col+1; i < mat->cols; i++) {
800
Z[j][i] *= waste;
801
}
802
}
803
}
804
}
805
806
if(!(mat->flags.Diagonal)) {
807
mat->flags.Symmetric = FALSE;
808
}
809
if(mat->kgv != 1) {
810
mat->flags.Integral = FALSE;
811
}
812
Check_mat(mat);
813
return(TRUE);
814
}
815
/*}}} */
816
817
/*{{{ iadd_row*/
818
/*
819
@-------------------------------------------------------------------------
820
@ boolean iadd_row(mat,t_row, d_row, v)
821
@ matrix_TYP *mat;
822
@ int t_row, d_row, v;
823
@
824
@ Add v-times t_row to d_row of mat, where v is an integer
825
@
826
@-------------------------------------------------------------------------
827
*/
828
boolean iadd_row(mat,t_row, d_row, v)
829
matrix_TYP *mat;
830
int t_row, d_row, v;
831
{
832
int **Z, i,j,t;
833
834
if((t_row >= mat->rows) || (d_row >= mat->rows)) {
835
fprintf(stderr,"Error in iadd_row: not so many rows!\n");
836
return(FALSE);
837
}
838
839
if( mat->prime ) {
840
if((v %= mat->prime) < 0) v += mat->prime;
841
}
842
if(v == 0) {
843
return(TRUE);
844
}
845
if((mat->prime == 0) && (mat->kgv == 0)) {
846
return(TRUE);
847
}
848
849
if(d_row == t_row) {
850
fprintf(stderr,"Warning: Same t_row and d_row in iadd_row\n");
851
return(imul_row(mat,t_row,v+1));
852
}
853
854
Z = mat->array.SZ;
855
if( mat->prime != 0 ) {
856
init_prime(mat->prime);
857
if(mat->flags.Diagonal) {
858
Z[d_row][t_row] = P(v,Z[t_row][t_row]);
859
if(Z[d_row][t_row]) {
860
mat->flags.Symmetric =
861
mat->flags.Diagonal = FALSE;
862
}
863
} else {
864
for(i = 0; i < mat->cols; i++) {
865
Z[d_row][i] = S(Z[d_row][i],P(v,Z[t_row][i]));
866
}
867
}
868
Check_mat(mat);
869
return(TRUE);
870
}
871
if(mat->flags.Diagonal) {
872
if(Z[t_row][t_row] ) {
873
i = Z[t_row][t_row] * v;
874
Z[d_row][t_row] = i;
875
mat->flags.Symmetric =
876
mat->flags.Diagonal = FALSE;
877
}
878
} else { /* diagonal */
879
j = find_max_entry( mat );
880
for(i = 0; i < mat->cols; i++) {
881
Z[d_row][i] += v * Z[t_row][i];
882
t = abs(Z[d_row][i]);
883
if(t > j) {
884
j = t;
885
}
886
}
887
mat->flags.Symmetric = FALSE;
888
}
889
Check_mat(mat);
890
return(TRUE);
891
}
892
/*}}} */
893
/*{{{ radd_row*/
894
/*
895
@-------------------------------------------------------------------------
896
@ boolean radd_row(mat,t_row, d_row, v)
897
@ matrix_TYP *mat;
898
@ int t_row, d_row;
899
@ rational v;
900
@
901
@ Add v-times t_row to d_row of mat, where v is a rational
902
@
903
@-------------------------------------------------------------------------
904
*/
905
boolean radd_row(mat,t_row, d_row, v)
906
matrix_TYP *mat;
907
int t_row, d_row;
908
rational v;
909
{
910
int **Z, i, j;
911
int waste,t;
912
913
if((t_row >= mat->rows) || (d_row >= mat->rows)) {
914
fprintf(stderr,"Error in radd_row: not so many rows!\n");
915
return(FALSE);
916
}
917
waste = t = 0;
918
919
if( mat->prime != 0) {
920
waste= (v.z%v.n)%mat->prime;
921
return(iadd_row(mat,t_row, d_row, waste));
922
}
923
if(v.z == 0) {
924
return(TRUE);
925
}
926
if( null_mat( mat ) ) {
927
return(TRUE);
928
}
929
if(v.n == 1) {
930
return(iadd_row(mat,t_row, d_row, v.z));
931
}
932
933
if(d_row == t_row) {
934
fprintf(stderr,"Warning: Same t_row and d_row in ladd_row\n");
935
v.z += v.n;
936
i = rmul_row(mat,t_row,v);
937
v.z -= v.n;
938
return(i);
939
}
940
941
Z = mat->array.SZ;
942
if(mat->flags.Diagonal) {
943
if(Z[t_row][t_row] != 0) {
944
mat->flags.Symmetric =
945
mat->flags.Diagonal = FALSE;
946
Z[d_row][t_row]= v.z*Z[t_row][t_row];
947
waste= GGT(Z[d_row][t_row],v.n);
948
if(v.n == waste) {
949
Z[d_row][t_row] /= v.n;
950
} else {
951
t= v.n/waste;
952
Z[d_row][t_row] /= waste;
953
mat->kgv *= t;
954
for(i = 0; i < mat->rows; i++) {
955
Z[i][i] *= t;
956
}
957
mat->flags.Integral = FALSE;
958
}
959
}
960
} else {
961
t= v.n;
962
for(i = 0; i < mat->cols; i++) {
963
Z[d_row][i]=Z[d_row][i]*v.n+Z[t_row][i]*v.z;
964
if((t != 1) && (Z[d_row][i] != 0)) {
965
waste= GGT(Z[d_row][i],t);
966
t = waste;
967
waste = 0;
968
}
969
}
970
if(t == v.n) {/* the lucky case: row-entries divisible by v.n! */
971
for(i = 0; i < mat->cols; i++) {
972
Z[d_row][i] /= v.n;
973
}
974
} else if( t == 1) { /* the opposite case: no common factor */
975
mat->kgv *= v.n;
976
for(j = 0; j < mat->cols; j++) {
977
for (i = 0; i < d_row; i++) {
978
Z[i][j] *= v.n;
979
}
980
for (i = d_row+1; i < mat->rows; i++) {
981
Z[i][j] *= v.n;
982
}
983
}
984
mat->flags.Integral = FALSE;
985
} else { /* something between the last two cases: most work */
986
waste = v.n / t;
987
mat->kgv *= waste;
988
for(j = 0; j < mat->cols; j++) {
989
for (i = 0; i < d_row; i++) {
990
Z[i][j] *= waste;
991
}
992
for (i = d_row+1; i < mat->rows; i++) {
993
Z[i][j] *= waste;
994
}
995
Z[d_row][j] /= t;
996
}
997
mat->flags.Integral = FALSE;
998
}
999
}
1000
1001
Check_mat(mat);
1002
return(TRUE);
1003
}
1004
/*}}} */
1005
1006
1007
/*{{{ iadd_col*/
1008
/*
1009
@-------------------------------------------------------------------------
1010
@ boolean iadd_col(mat,t_col, d_col, v)
1011
@ matrix_TYP *mat;
1012
@ int t_col, d_col, v;
1013
@
1014
@ Add v-times t_col to d_col of mat, where v is an integer
1015
@
1016
@-------------------------------------------------------------------------
1017
*/
1018
boolean iadd_col(mat,t_col, d_col, v)
1019
matrix_TYP *mat;
1020
int t_col, d_col, v;
1021
{
1022
int **Z, i,j,t;
1023
1024
if((t_col >= mat->cols) || (d_col >= mat->cols)) {
1025
fprintf(stderr,"Error in iadd_row: not so many rows!\n");
1026
return(FALSE);
1027
}
1028
if( mat->prime != 0 ) {
1029
if((v %= mat->prime) < 0) v += mat->prime;
1030
}
1031
if(v == 0) {
1032
return(TRUE);
1033
}
1034
1035
if( null_mat( mat ) ) {
1036
return(TRUE);
1037
}
1038
1039
if(d_col == t_col) {
1040
fprintf(stderr,"Warning: Same t_col and d_col in iadd_col\n");
1041
return(imul_col(mat,t_col,v+1));
1042
}
1043
1044
Z = mat->array.SZ;
1045
if( mat->prime != 0 ) {
1046
init_prime(mat->prime);
1047
if(mat->flags.Diagonal) {
1048
Z[t_col][d_col] = P(v,Z[t_col][t_col]);
1049
if(Z[t_col][d_col]) {
1050
mat->flags.Symmetric =
1051
mat->flags.Diagonal = FALSE;
1052
}
1053
} else {
1054
for(i = 0; i < mat->rows; i++) {
1055
Z[i][d_col] = S(Z[i][d_col],P(v,Z[i][t_col]));
1056
}
1057
}
1058
Check_mat(mat);
1059
return(TRUE);
1060
}
1061
if(mat->flags.Diagonal) {
1062
if(Z[t_col][t_col] ) {
1063
i = Z[t_col][t_col] * v;
1064
Z[t_col][d_col] = i;
1065
mat->flags.Symmetric =
1066
mat->flags.Diagonal = FALSE;
1067
}
1068
} else {
1069
j = find_max_entry( mat );
1070
for(i = 0; i < mat->rows; i++) {
1071
Z[i][d_col] += v * Z[i][t_col];
1072
t = abs(Z[i][d_col]);
1073
if(t > j) {
1074
j = t;
1075
}
1076
}
1077
mat->flags.Symmetric = FALSE;
1078
}
1079
Check_mat(mat);
1080
return(TRUE);
1081
}
1082
/*}}} */
1083
/*{{{ radd_col*/
1084
/*
1085
@-------------------------------------------------------------------------
1086
@ boolean radd_col(mat,t_col, d_col, v)
1087
@ matrix_TYP *mat;
1088
@ int t_col, d_col;
1089
@ rational v;
1090
@
1091
@ Add v-times t_col to d_col of mat, where v is a rational
1092
@
1093
@-------------------------------------------------------------------------
1094
*/
1095
boolean radd_col(mat,t_col, d_col, v)
1096
matrix_TYP *mat;
1097
int t_col, d_col;
1098
rational v;
1099
{
1100
int **Z, i,j;
1101
int waste,t;
1102
1103
if((t_col >= mat->cols) || (d_col >= mat->cols)) {
1104
fprintf(stderr,"Error in radd_col: not so many cols!\n");
1105
return(FALSE);
1106
}
1107
waste = t = 0;
1108
1109
if( mat->prime != 0) {
1110
return(iadd_col(mat,t_col, d_col, (v.z%v.n)%mat->prime));
1111
}
1112
if(v.z == 0) {
1113
return(TRUE);
1114
}
1115
if( null_mat( mat ) ) {
1116
return(TRUE);
1117
}
1118
if(v.n == 1) {
1119
return(iadd_col(mat,t_col, d_col, v.z));
1120
}
1121
1122
if(d_col == t_col) {
1123
fprintf(stderr,"Warning: Same t_col and d_col in radd_col\n");
1124
v.z += v.n;
1125
i = rmul_row(mat,t_col,v);
1126
v.z -= v.n;
1127
return(i);
1128
}
1129
1130
Z = mat->array.SZ;
1131
if(mat->flags.Diagonal) {
1132
if(Z[t_col][t_col] != 0) {
1133
mat->flags.Symmetric =
1134
mat->flags.Diagonal = FALSE;
1135
Z[t_col][d_col] = v.z * Z[t_col][t_col];
1136
waste = GGT(Z[t_col][d_col],v.n);
1137
if(v.n == waste) {
1138
Z[t_col][d_col]/= v.n;
1139
} else {
1140
t = v.n / waste;
1141
Z[t_col][d_col] /= waste;
1142
mat->kgv *= t;
1143
for(i = 0; i < mat->rows; i++) {
1144
Z[i][i] *= t;
1145
}
1146
mat->flags.Integral = FALSE;
1147
}
1148
}
1149
} else {
1150
t = v.n;
1151
for(i = 0; i < mat->rows; i++) {
1152
Z[i][d_col] = Z[i][d_col] * v.n + Z[i][t_col] * v.z;
1153
if((t != 1) && (Z[i][d_col] != 0)) {
1154
waste= GGT(Z[i][d_col],t);
1155
t = waste;
1156
waste = 0;
1157
}
1158
}
1159
if( t == v.n ) {/* the lucky case: row-entries divisible by v.n! */
1160
for(i = 0; i < mat->rows; i++) {
1161
Z[i][d_col] /= v.n;
1162
}
1163
} else if( t == 1) { /* the opposite case: no common factor */
1164
mat->kgv *= v.n;
1165
for(j = 0; j < mat->rows; j++) {
1166
for (i = 0; i < d_col; i++) {
1167
Z[j][i] *= v.n;
1168
}
1169
for (i = d_col+1; i < mat->cols; i++) {
1170
Z[j][i] *= v.n;
1171
}
1172
}
1173
mat->flags.Integral = FALSE;
1174
} else { /* something between the last two cases: most work */
1175
waste= v.n / t;
1176
mat->kgv *= waste;
1177
for(j = 0; j < mat->rows; j++) {
1178
for (i = 0; i < d_col; i++) {
1179
Z[j][i] *= waste;
1180
}
1181
for (i = d_col+1; i < mat->cols; i++) {
1182
Z[j][i] *= waste;
1183
}
1184
Z[j][d_col] /= t;
1185
}
1186
mat->flags.Integral = FALSE;
1187
}
1188
}
1189
Check_mat(mat);
1190
return(TRUE);
1191
}
1192
/*}}} */
1193
/*{{{ normal_rows*/
1194
/*
1195
@-------------------------------------------------------------------------
1196
@ void normal_rows(mat);
1197
@ matrix_TYP *mat;
1198
@
1199
@ Tool for integral Gauss-elimination: the entries of the
1200
@ rows of mat are divided by their row-gcd.
1201
@
1202
@-------------------------------------------------------------------------
1203
*/
1204
void normal_rows(mat)
1205
matrix_TYP *mat;
1206
{
1207
int i,j, g;
1208
int **Z, *S_I;
1209
1210
if( mat->flags.Diagonal || (mat->prime != 0) || null_mat( mat) ) {
1211
return;
1212
}
1213
Z = mat->array.SZ;
1214
g = 0;
1215
for(i = 0; i < mat->rows; i++) {
1216
S_I = Z[i];
1217
g = 0;
1218
for(j = 0; j < mat->cols; j++) {
1219
if(S_I[j]) g = GGT(g,S_I[j]);
1220
if(g == 1) j = mat->cols;
1221
}
1222
if(g != 1) {
1223
for(j = 0; j < mat->cols; j++) {
1224
if(S_I[j]) {
1225
S_I[j] /= g;
1226
}
1227
}
1228
}
1229
}
1230
}
1231
/*}}} */
1232
/*{{{ normal_cols*/
1233
/*
1234
@-------------------------------------------------------------------------
1235
@ void normal_cols(mat)
1236
@
1237
@ Analogue to normal_rows() function for cols
1238
@
1239
@-------------------------------------------------------------------------
1240
*/
1241
void normal_cols(mat)
1242
matrix_TYP *mat;
1243
{
1244
int i,j, g;
1245
int **Z;
1246
1247
if( mat->flags.Diagonal || (mat->prime != 0) || null_mat( mat ) ) {
1248
return;
1249
}
1250
1251
Z = mat->array.SZ;
1252
g = 0;
1253
for(i = 0; i < mat->cols; i++) {
1254
g = 0;
1255
for(j = 0; j < mat->rows; j++) {
1256
if(Z[j][i]) {
1257
g = GGT(g,Z[j][i]);
1258
}
1259
if(g == 1) {
1260
j = mat->rows;
1261
}
1262
}
1263
if(g != 1) {
1264
for(j = 0; j < mat->rows; j++) {
1265
if(Z[j][i]) {
1266
Z[j][i] /= g;
1267
}
1268
}
1269
}
1270
}
1271
}
1272
/*}}} */
1273
/*{{{ mat_to_line*/
1274
/*
1275
@-------------------------------------------------------------------------
1276
@ matrix_TYP *mat_to_line(gen, num);
1277
@ matrix_TYP **gen;
1278
@ int num;
1279
@
1280
@ matrix_TYP **gen;
1281
@ int num;
1282
@
1283
@ converts each matrix of gen into a row-vector, forgets the kgv.
1284
@ the i-th matrix is converted to the i-th row of the result.
1285
@ Tool for determine a basis of a vector space of matrices
1286
@
1287
@-------------------------------------------------------------------------
1288
*/
1289
matrix_TYP *mat_to_line(gen, num)
1290
matrix_TYP **gen;
1291
int num;
1292
{
1293
matrix_TYP *mat;
1294
int i, j, k, row, col;
1295
int **Z, **ZI;
1296
1297
row = gen[0]->rows;
1298
col = gen[0]->cols;
1299
for(i = 0; i < num; i++) {
1300
if((row != gen[i]->rows) || (col != gen[i]->cols)) {
1301
fprintf(stderr,"Fehler: verschiedene Dimensionen in mat_to_line\n");
1302
exit(3);
1303
}
1304
}
1305
mat = init_mat(num, row * col,"");
1306
Z = mat->array.SZ;
1307
for(k = 0; k < num; k++) {
1308
ZI = gen[k]->array.SZ;
1309
for(j = 0; j < row; j++) {
1310
memcpy(Z[k]+j*col,ZI[j],col*sizeof(int));
1311
}
1312
}
1313
return(mat);
1314
}
1315
1316
/*}}} */
1317
/*{{{ line_to_mat*/
1318
/*
1319
@-------------------------------------------------------------------------
1320
@ matrix_TYP **line_to_mat(mat,row,col)
1321
@ matrix_TYP *mat;
1322
@ int row, col;
1323
@
1324
@ Inverse function to mat_to_line
1325
@
1326
@-------------------------------------------------------------------------
1327
*/
1328
matrix_TYP **line_to_mat(mat,row,col)
1329
matrix_TYP *mat;
1330
int row, col;
1331
{
1332
matrix_TYP **gen;
1333
int i,k;
1334
int **Z, **ZI;
1335
1336
if(mat->cols != row* col) {
1337
fprintf(stderr,"Fehler in line_to_mat: Falsche Dimensionierung\n");
1338
exit(3);
1339
}
1340
gen = (matrix_TYP **)malloc(mat->rows * sizeof(matrix_TYP *));
1341
1342
for(k = 0; k < mat->rows; k++) {
1343
Z = mat->array.SZ;
1344
gen[k] = init_mat(row, col, "");
1345
ZI = gen[k]->array.SZ;
1346
for(i = 0; i < mat->cols; i++) {
1347
ZI[i / col][i % col] = Z[k][i];
1348
}
1349
Check_mat(gen[k]);
1350
}
1351
return(gen);
1352
}
1353
1354
/*}}} */
1355
/*{{{ normal_mat*/
1356
/*
1357
@-------------------------------------------------------------------------
1358
@ int normal_mat(mat);
1359
@ matrix_TYP *mat;
1360
@
1361
@ Calculate ggt of mat-entries and divide matrix by it
1362
@ Return value is the ggt
1363
@
1364
@-------------------------------------------------------------------------
1365
*/
1366
int normal_mat(mat)
1367
matrix_TYP *mat;
1368
{
1369
int i,j, g;
1370
int **Z, *S_I;
1371
1372
if( null_mat(mat) || (mat->prime != 0)) {
1373
return(1);
1374
}
1375
1376
Z = mat->array.SZ;
1377
g = 0;
1378
if(mat->flags.Diagonal) {
1379
for(i = 0; i < mat->rows; i++) {
1380
if(Z[i][i]) g = GGT(g,Z[i][i]);
1381
if(g == 1) {
1382
i = mat->rows;
1383
}
1384
}
1385
} else {
1386
g = 0;
1387
for(i = 0; i < mat->rows; i++) {
1388
S_I = Z[i];
1389
for(j = 0; j < mat->cols; j++) {
1390
if(S_I[j]) {
1391
g = GGT(g,S_I[j]);
1392
}
1393
if(g == 1) {
1394
j = mat->cols;
1395
i = mat->rows;
1396
}
1397
}
1398
}
1399
}
1400
if(g != 1) {
1401
for(i = 0; i < mat->rows; i++) {
1402
S_I = Z[i];
1403
for(j = 0; j < mat->cols; j++) {
1404
if(S_I[j]) S_I[j] /= g;
1405
}
1406
}
1407
}
1408
return(g);
1409
}
1410
/*}}} */
1411
1412
1413