source: git/ntl/src/mat_GF2E.c @ 311902

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