source: git/ntl/src/mat_lzz_p.c @ 54e84ca

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