source: git/ntl/src/mat_GF2E.c @ 2cfffe

spielwiese
Last change on this file since 2cfffe was 2cfffe, checked in by Hans Schönemann <hannes@…>, 21 years ago
This commit was generated by cvs2svn to compensate for changes in r6316, which included commits to RCS files with non-trunk default branches. git-svn-id: file:///usr/local/Singular/svn/trunk@6317 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 14.5 KB
Line 
1
2#include <NTL/mat_GF2E.h>
3#include <NTL/vec_GF2XVec.h>
4#include <NTL/vec_long.h>
5
6#include <NTL/new.h>
7
8NTL_START_IMPL
9
10NTL_matrix_impl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
11NTL_io_matrix_impl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
12NTL_eq_matrix_impl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
13
14
15 
16void add(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B) 
17{ 
18   long n = A.NumRows(); 
19   long m = A.NumCols(); 
20 
21   if (B.NumRows() != n || B.NumCols() != m)   
22      Error("matrix add: dimension mismatch"); 
23 
24   X.SetDims(n, m); 
25 
26   long i, j; 
27   for (i = 1; i <= n; i++)   
28      for (j = 1; j <= m; j++) 
29         add(X(i,j), A(i,j), B(i,j)); 
30} 
31 
32void mul_aux(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B) 
33{ 
34   long n = A.NumRows(); 
35   long l = A.NumCols(); 
36   long m = B.NumCols(); 
37 
38   if (l != B.NumRows()) 
39      Error("matrix mul: dimension mismatch"); 
40 
41   X.SetDims(n, m); 
42 
43   long i, j, k; 
44   GF2X acc, tmp; 
45 
46   for (i = 1; i <= n; i++) { 
47      for (j = 1; j <= m; j++) { 
48         clear(acc); 
49         for(k = 1; k <= l; k++) { 
50            mul(tmp, rep(A(i,k)), rep(B(k,j))); 
51            add(acc, acc, tmp); 
52         } 
53         conv(X(i,j), acc); 
54      } 
55   } 
56} 
57 
58 
59void mul(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B) 
60{ 
61   if (&X == &A || &X == &B) { 
62      mat_GF2E tmp; 
63      mul_aux(tmp, A, B); 
64      X = tmp; 
65   } 
66   else 
67      mul_aux(X, A, B); 
68} 
69 
70 
71static
72void mul_aux(vec_GF2E& x, const mat_GF2E& A, const vec_GF2E& b) 
73{ 
74   long n = A.NumRows(); 
75   long l = A.NumCols(); 
76 
77   if (l != b.length()) 
78      Error("matrix mul: dimension mismatch"); 
79 
80   x.SetLength(n); 
81 
82   long i, k; 
83   GF2X acc, tmp; 
84 
85   for (i = 1; i <= n; i++) { 
86      clear(acc); 
87      for (k = 1; k <= l; k++) { 
88         mul(tmp, rep(A(i,k)), rep(b(k))); 
89         add(acc, acc, tmp); 
90      } 
91      conv(x(i), acc); 
92   } 
93} 
94 
95 
96void mul(vec_GF2E& x, const mat_GF2E& A, const vec_GF2E& b) 
97{ 
98   if (&b == &x || A.position(b) != -1) {
99      vec_GF2E tmp;
100      mul_aux(tmp, A, b);
101      x = tmp;
102   }
103   else
104      mul_aux(x, A, b);
105} 
106
107static
108void mul_aux(vec_GF2E& x, const vec_GF2E& a, const mat_GF2E& B) 
109{ 
110   long n = B.NumRows(); 
111   long l = B.NumCols(); 
112 
113   if (n != a.length()) 
114      Error("matrix mul: dimension mismatch"); 
115 
116   x.SetLength(l); 
117 
118   long i, k; 
119   GF2X acc, tmp; 
120 
121   for (i = 1; i <= l; i++) { 
122      clear(acc); 
123      for (k = 1; k <= n; k++) { 
124         mul(tmp, rep(a(k)), rep(B(k,i)));
125         add(acc, acc, tmp); 
126      } 
127      conv(x(i), acc); 
128   } 
129} 
130
131void mul(vec_GF2E& x, const vec_GF2E& a, const mat_GF2E& B)
132{
133   if (&a == &x || B.position(a) != -1) {
134      vec_GF2E tmp;
135      mul_aux(tmp, a, B);
136      x = tmp;
137   }
138   else
139      mul_aux(x, a, B);
140}
141
142     
143 
144void ident(mat_GF2E& X, long n) 
145{ 
146   X.SetDims(n, n); 
147   long i, j; 
148 
149   for (i = 1; i <= n; i++) 
150      for (j = 1; j <= n; j++) 
151         if (i == j) 
152            set(X(i, j)); 
153         else 
154            clear(X(i, j)); 
155} 
156
157
158void determinant(GF2E& d, const mat_GF2E& M_in)
159{
160   long k, n;
161   long i, j;
162   long pos;
163   GF2X t1, t2;
164   GF2X *x, *y;
165
166   const GF2XModulus& p = GF2E::modulus();
167
168   n = M_in.NumRows();
169
170   if (M_in.NumCols() != n)
171      Error("determinant: nonsquare matrix");
172
173   if (n == 0) {
174      set(d);
175      return;
176   }
177
178   vec_GF2XVec M;
179
180   M.SetLength(n);
181   for (i = 0; i < n; i++) {
182      M[i].SetSize(n, 2*GF2E::WordLength());
183      for (j = 0; j < n; j++)
184         M[i][j] = rep(M_in[i][j]);
185   }
186
187   GF2X det;
188   set(det);
189
190   for (k = 0; k < n; k++) {
191      pos = -1;
192      for (i = k; i < n; i++) {
193         rem(t1, M[i][k], p);
194         M[i][k] = t1;
195         if (pos == -1 && !IsZero(t1))
196            pos = i;
197      }
198
199      if (pos != -1) {
200         if (k != pos) {
201            swap(M[pos], M[k]);
202         }
203
204         MulMod(det, det, M[k][k], p);
205
206         // make M[k, k] == -1 mod p, and make row k reduced
207
208         InvMod(t1, M[k][k], p);
209         for (j = k+1; j < n; j++) {
210            rem(t2, M[k][j], p);
211            MulMod(M[k][j], t2, t1, p);
212         }
213
214         for (i = k+1; i < n; i++) {
215            // M[i] = M[i] + M[k]*M[i,k]
216
217            t1 = M[i][k];   // this is already reduced
218
219            x = M[i].elts() + (k+1);
220            y = M[k].elts() + (k+1);
221
222            for (j = k+1; j < n; j++, x++, y++) {
223               // *x = *x + (*y)*t1
224
225               mul(t2, *y, t1);
226               add(*x, *x, t2);
227            }
228         }
229      }
230      else {
231         clear(d);
232         return;
233      }
234   }
235
236   conv(d, det);
237}
238
239long IsIdent(const mat_GF2E& A, long n)
240{
241   if (A.NumRows() != n || A.NumCols() != n)
242      return 0;
243
244   long i, j;
245
246   for (i = 1; i <= n; i++)
247      for (j = 1; j <= n; j++)
248         if (i != j) {
249            if (!IsZero(A(i, j))) return 0;
250         }
251         else {
252            if (!IsOne(A(i, j))) return 0;
253         }
254
255   return 1;
256}
257           
258
259void transpose(mat_GF2E& X, const mat_GF2E& A)
260{
261   long n = A.NumRows();
262   long m = A.NumCols();
263
264   long i, j;
265
266   if (&X == & A) {
267      if (n == m)
268         for (i = 1; i <= n; i++)
269            for (j = i+1; j <= n; j++)
270               swap(X(i, j), X(j, i));
271      else {
272         mat_GF2E tmp;
273         tmp.SetDims(m, n);
274         for (i = 1; i <= n; i++)
275            for (j = 1; j <= m; j++)
276               tmp(j, i) = A(i, j);
277         X.kill();
278         X = tmp;
279      }
280   }
281   else {
282      X.SetDims(m, n);
283      for (i = 1; i <= n; i++)
284         for (j = 1; j <= m; j++)
285            X(j, i) = A(i, j);
286   }
287}
288   
289
290void solve(GF2E& d, vec_GF2E& X, 
291           const mat_GF2E& A, const vec_GF2E& b)
292
293{
294   long n = A.NumRows();
295   if (A.NumCols() != n)
296      Error("solve: nonsquare matrix");
297
298   if (b.length() != n)
299      Error("solve: dimension mismatch");
300
301   if (n == 0) {
302      set(d);
303      X.SetLength(0);
304      return;
305   }
306
307   long i, j, k, pos;
308   GF2X t1, t2;
309   GF2X *x, *y;
310
311   const GF2XModulus& p = GF2E::modulus();
312
313   vec_GF2XVec M;
314
315   M.SetLength(n);
316
317   for (i = 0; i < n; i++) {
318      M[i].SetSize(n+1, 2*GF2E::WordLength());
319      for (j = 0; j < n; j++) 
320         M[i][j] = rep(A[j][i]);
321      M[i][n] = rep(b[i]);
322   }
323
324   GF2X det;
325   set(det);
326
327   for (k = 0; k < n; k++) {
328      pos = -1;
329      for (i = k; i < n; i++) {
330         rem(t1, M[i][k], p);
331         M[i][k] = t1;
332         if (pos == -1 && !IsZero(t1)) {
333            pos = i;
334         }
335      }
336
337      if (pos != -1) {
338         if (k != pos) {
339            swap(M[pos], M[k]);
340         }
341
342         MulMod(det, det, M[k][k], p);
343
344         // make M[k, k] == -1 mod p, and make row k reduced
345
346         InvMod(t1, M[k][k], p);
347         for (j = k+1; j <= n; j++) {
348            rem(t2, M[k][j], p);
349            MulMod(M[k][j], t2, t1, p);
350         }
351
352         for (i = k+1; i < n; i++) {
353            // M[i] = M[i] + M[k]*M[i,k]
354
355            t1 = M[i][k];   // this is already reduced
356
357            x = M[i].elts() + (k+1);
358            y = M[k].elts() + (k+1);
359
360            for (j = k+1; j <= n; j++, x++, y++) {
361               // *x = *x + (*y)*t1
362
363               mul(t2, *y, t1);
364               add(*x, *x, t2);
365            }
366         }
367      }
368      else {
369         clear(d);
370         return;
371      }
372   }
373
374   X.SetLength(n);
375   for (i = n-1; i >= 0; i--) {
376      clear(t1);
377      for (j = i+1; j < n; j++) {
378         mul(t2, rep(X[j]), M[i][j]);
379         add(t1, t1, t2);
380      }
381      add(t1, t1, M[i][n]);
382      conv(X[i], t1);
383   }
384
385   conv(d, det);
386}
387
388void inv(GF2E& d, mat_GF2E& X, const mat_GF2E& A)
389{
390   long n = A.NumRows();
391   if (A.NumCols() != n)
392      Error("inv: nonsquare matrix");
393
394   if (n == 0) {
395      set(d);
396      X.SetDims(0, 0);
397      return;
398   }
399
400   long i, j, k, pos;
401   GF2X t1, t2;
402   GF2X *x, *y;
403
404   const GF2XModulus& p = GF2E::modulus();
405
406   vec_GF2XVec M;
407
408   M.SetLength(n);
409
410   for (i = 0; i < n; i++) {
411      M[i].SetSize(2*n, 2*GF2E::WordLength());
412      for (j = 0; j < n; j++) {
413         M[i][j] = rep(A[i][j]);
414         clear(M[i][n+j]);
415      }
416      set(M[i][n+i]);
417   }
418
419   GF2X det;
420   set(det);
421
422   for (k = 0; k < n; k++) {
423      pos = -1;
424      for (i = k; i < n; i++) {
425         rem(t1, M[i][k], p);
426         M[i][k] = t1;
427         if (pos == -1 && !IsZero(t1)) {
428            pos = i;
429         }
430      }
431
432      if (pos != -1) {
433         if (k != pos) {
434            swap(M[pos], M[k]);
435         }
436
437         MulMod(det, det, M[k][k], p);
438
439         // make M[k, k] == -1 mod p, and make row k reduced
440
441         InvMod(t1, M[k][k], p);
442         for (j = k+1; j < 2*n; j++) {
443            rem(t2, M[k][j], p);
444            MulMod(M[k][j], t2, t1, p);
445         }
446
447         for (i = k+1; i < n; i++) {
448            // M[i] = M[i] + M[k]*M[i,k]
449
450            t1 = M[i][k];   // this is already reduced
451
452            x = M[i].elts() + (k+1);
453            y = M[k].elts() + (k+1);
454
455            for (j = k+1; j < 2*n; j++, x++, y++) {
456               // *x = *x + (*y)*t1
457
458               mul(t2, *y, t1);
459               add(*x, *x, t2);
460            }
461         }
462      }
463      else {
464         clear(d);
465         return;
466      }
467   }
468
469   X.SetDims(n, n);
470   for (k = 0; k < n; k++) {
471      for (i = n-1; i >= 0; i--) {
472         clear(t1);
473         for (j = i+1; j < n; j++) {
474            mul(t2, rep(X[j][k]), M[i][j]);
475            add(t1, t1, t2);
476         }
477         add(t1, t1, M[i][n+k]);
478         conv(X[i][k], t1);
479      }
480   }
481
482   conv(d, det);
483}
484
485
486
487long gauss(mat_GF2E& M_in, long w)
488{
489   long k, l;
490   long i, j;
491   long pos;
492   GF2X t1, t2, t3;
493   GF2X *x, *y;
494
495   long n = M_in.NumRows();
496   long m = M_in.NumCols();
497
498   if (w < 0 || w > m)
499      Error("gauss: bad args");
500
501   const GF2XModulus& p = GF2E::modulus();
502
503   vec_GF2XVec M;
504
505   M.SetLength(n);
506   for (i = 0; i < n; i++) {
507      M[i].SetSize(m, 2*GF2E::WordLength());
508      for (j = 0; j < m; j++) {
509         M[i][j] = rep(M_in[i][j]);
510      }
511   }
512
513   l = 0;
514   for (k = 0; k < w && l < n; k++) {
515
516      pos = -1;
517      for (i = l; i < n; i++) {
518         rem(t1, M[i][k], p);
519         M[i][k] = t1;
520         if (pos == -1 && !IsZero(t1)) {
521            pos = i;
522         }
523      }
524
525      if (pos != -1) {
526         swap(M[pos], M[l]);
527
528         InvMod(t3, M[l][k], p);
529
530         for (j = k+1; j < m; j++) {
531            rem(M[l][j], M[l][j], p);
532         }
533
534         for (i = l+1; i < n; i++) {
535            // M[i] = M[i] + M[l]*M[i,k]*t3
536
537            MulMod(t1, M[i][k], t3, p);
538
539            clear(M[i][k]);
540
541            x = M[i].elts() + (k+1);
542            y = M[l].elts() + (k+1);
543
544            for (j = k+1; j < m; j++, x++, y++) {
545               // *x = *x + (*y)*t1
546
547               mul(t2, *y, t1);
548               add(t2, t2, *x);
549               *x = t2;
550            }
551         }
552
553         l++;
554      }
555   }
556   
557   for (i = 0; i < n; i++)
558      for (j = 0; j < m; j++)
559         conv(M_in[i][j], M[i][j]);
560
561   return l;
562}
563
564long gauss(mat_GF2E& M)
565{
566   return gauss(M, M.NumCols());
567}
568
569void image(mat_GF2E& X, const mat_GF2E& A)
570{
571   mat_GF2E M;
572   M = A;
573   long r = gauss(M);
574   M.SetDims(r, M.NumCols());
575   X = M;
576}
577
578void kernel(mat_GF2E& X, const mat_GF2E& A)
579{
580   long m = A.NumRows();
581   long n = A.NumCols();
582
583   mat_GF2E M;
584   long r;
585
586   transpose(M, A);
587   r = gauss(M);
588
589   X.SetDims(m-r, m);
590
591   long i, j, k, s;
592   GF2X t1, t2;
593
594   GF2E T3;
595
596   vec_long D;
597   D.SetLength(m);
598   for (j = 0; j < m; j++) D[j] = -1;
599
600   vec_GF2E inverses;
601   inverses.SetLength(m);
602
603   j = -1;
604   for (i = 0; i < r; i++) {
605      do {
606         j++;
607      } while (IsZero(M[i][j]));
608
609      D[j] = i;
610      inv(inverses[j], M[i][j]); 
611   }
612
613   for (k = 0; k < m-r; k++) {
614      vec_GF2E& v = X[k];
615      long pos = 0;
616      for (j = m-1; j >= 0; j--) {
617         if (D[j] == -1) {
618            if (pos == k)
619               set(v[j]);
620            else
621               clear(v[j]);
622            pos++;
623         }
624         else {
625            i = D[j];
626
627            clear(t1);
628
629            for (s = j+1; s < m; s++) {
630               mul(t2, rep(v[s]), rep(M[i][s]));
631               add(t1, t1, t2);
632            }
633
634            conv(T3, t1);
635            mul(T3, T3, inverses[j]);
636            v[j] = T3;
637         }
638      }
639   }
640}
641   
642void mul(mat_GF2E& X, const mat_GF2E& A, const GF2E& b_in)
643{
644   GF2E b = b_in;
645   long n = A.NumRows();
646   long m = A.NumCols();
647
648   X.SetDims(n, m);
649
650   long i, j;
651   for (i = 0; i < n; i++)
652      for (j = 0; j < m; j++)
653         mul(X[i][j], A[i][j], b);
654}
655
656void mul(mat_GF2E& X, const mat_GF2E& A, GF2 b)
657{
658   X = A;
659   if (b == 0)
660      clear(X);
661}
662
663void diag(mat_GF2E& X, long n, const GF2E& d_in) 
664{ 
665   GF2E d = d_in;
666   X.SetDims(n, n); 
667   long i, j; 
668 
669   for (i = 1; i <= n; i++) 
670      for (j = 1; j <= n; j++) 
671         if (i == j) 
672            X(i, j) = d; 
673         else 
674            clear(X(i, j)); 
675} 
676
677long IsDiag(const mat_GF2E& A, long n, const GF2E& d)
678{
679   if (A.NumRows() != n || A.NumCols() != n)
680      return 0;
681
682   long i, j;
683
684   for (i = 1; i <= n; i++)
685      for (j = 1; j <= n; j++)
686         if (i != j) {
687            if (!IsZero(A(i, j))) return 0;
688         }
689         else {
690            if (A(i, j) != d) return 0;
691         }
692
693   return 1;
694}
695
696
697long IsZero(const mat_GF2E& a)
698{
699   long n = a.NumRows();
700   long i;
701
702   for (i = 0; i < n; i++)
703      if (!IsZero(a[i]))
704         return 0;
705
706   return 1;
707}
708
709void clear(mat_GF2E& x)
710{
711   long n = x.NumRows();
712   long i;
713   for (i = 0; i < n; i++)
714      clear(x[i]);
715}
716
717
718mat_GF2E operator+(const mat_GF2E& a, const mat_GF2E& b)
719{
720   mat_GF2E res;
721   add(res, a, b);
722   NTL_OPT_RETURN(mat_GF2E, res);
723}
724
725mat_GF2E operator*(const mat_GF2E& a, const mat_GF2E& b)
726{
727   mat_GF2E res;
728   mul_aux(res, a, b);
729   NTL_OPT_RETURN(mat_GF2E, res);
730}
731
732mat_GF2E operator-(const mat_GF2E& a, const mat_GF2E& b)
733{
734   mat_GF2E res;
735   sub(res, a, b);
736   NTL_OPT_RETURN(mat_GF2E, res);
737}
738
739
740mat_GF2E operator-(const mat_GF2E& a)
741{
742   mat_GF2E res;
743   negate(res, a);
744   NTL_OPT_RETURN(mat_GF2E, res);
745}
746
747
748vec_GF2E operator*(const mat_GF2E& a, const vec_GF2E& b)
749{
750   vec_GF2E res;
751   mul_aux(res, a, b);
752   NTL_OPT_RETURN(vec_GF2E, res);
753}
754
755vec_GF2E operator*(const vec_GF2E& a, const mat_GF2E& b)
756{
757   vec_GF2E res;
758   mul_aux(res, a, b);
759   NTL_OPT_RETURN(vec_GF2E, res);
760}
761
762
763void inv(mat_GF2E& X, const mat_GF2E& A)
764{
765   GF2E d;
766   inv(d, X, A);
767   if (d == 0) Error("inv: non-invertible matrix");
768}
769
770void power(mat_GF2E& X, const mat_GF2E& A, const ZZ& e)
771{
772   if (A.NumRows() != A.NumCols()) Error("power: non-square matrix");
773
774   if (e == 0) {
775      ident(X, A.NumRows());
776      return;
777   }
778
779   mat_GF2E T1, T2;
780   long i, k;
781
782   k = NumBits(e);
783   T1 = A;
784
785   for (i = k-2; i >= 0; i--) {
786      sqr(T2, T1);
787      if (bit(e, i))
788         mul(T1, T2, A);
789      else
790         T1 = T2;
791   }
792
793   if (e < 0)
794      inv(X, T1);
795   else
796      X = T1;
797}
798
799NTL_END_IMPL
Note: See TracBrowser for help on using the repository browser.