source: git/Singular/LIB/ASK.lib @ 449fbf

spielwiese
Last change on this file since 449fbf was 449fbf, checked in by Hans Schönemann <hannes@…>, 17 years ago
*** empty log message *** git-svn-id: file:///usr/local/Singular/svn/trunk@9565 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 13.7 KB
Line 
1//CM, last modified 10.12.06
2///////////////////////////////////////////////////////////////////////////////
3version="$Id: ASK.lib,v 1.1 2006-12-11 12:52:42 Singular Exp $";
4category="Teaching";
5info="
6LIBRARY: ASK.lib
7         PROCEDURES FOR PRIMALITY TESTING AFTER AGRAWAL, SAXENA, KAYAL
8AUTHORS: Christoph Mang
9
10OVERVIEV:
11 Algorithms for primality testing in polynomial time
12 based on the ideas of Agrawal, Saxena and  Kayal.
13
14
15
16
17PROCEDURES:
18
19
20schnellexp(a,m)            a^m for numbers a,m
21schnellexpt(a,m,n)         a^m for numbers a,m; if a^k>n n+1 is returned
22log2(n)                    logarithm to basis 2 of n
23PerfectPowerTest(n)        checks if there are a,b>1, so that a^b=n
24schnellexppoly(a,m)        a^m for number m,poly a
25wurzel(r)                  square root of number r
26euler(r)                   phi-function of euler
27coeffmod(f,n)              poly f modulo number n (coefficients mod n)
28powerpolyX(q,n,a,r)        (poly a)^q modulo (poly r,number n)
29ask(n)                     ASK-Algorithm; deterministic Primality test
30";
31
32LIB "krypto.lib";
33LIB "ntsolve.lib";
34
35
36
37
38
39///////////////////////////////////////////////////////////////
40//                                                           //
41//   Fast Exponentiation                                     //
42//                                                           //
43///////////////////////////////////////////////////////////////
44
45
46
47
48proc schnellexp(number a,number m)
49"USAGE: schnellexp(a,m);
50RETURN: the m-th power of a
51NOTE:   uses fast exponentiation
52EXAMPLE:example schnellexp; shows an example
53"
54{
55 number b,c,d;
56 c=m;
57 b=a;
58 d=1;
59
60  while(c>=1)
61  {
62    if((c mod 2)==1)
63     {
64       d=d*b;
65     }
66
67   b=b^2;
68   c=intPart(c/2);
69
70  }
71 return(d)
72}
73example
74{ "EXAMPLE:"; echo = 2;
75   ring R = 0,x,dp;
76   schnellexp(24,1234);
77}
78
79
80
81////////////////////////////////////////////////////////////////////////
82
83
84proc schnellexpt(number a,number m,number n)
85"USAGE: schnellexpt(a,m,n);
86RETURN: the m-th power of a; if a^m>n the procedure returns n+1
87NOTE:   uses fast exponentiation
88EXAMPLE:example schnellexpt; shows an example
89"
90{
91 number b,c,d;
92 c=m;
93 b=a;
94 d=1;
95
96  while(c>=1)
97  {
98   if(b>n)
99     {
100      return(n+1);
101     }
102
103    if((c mod 2)==1)
104     {
105       d=d*b;
106       if(d>n)
107        {
108          return(n+1);
109        }
110     }
111
112   b=b^2;
113   c=intPart(c/2);
114
115  }
116 return(d)
117}
118example
119{ "EXAMPLE:"; echo = 2;
120   ring R = 0,x,dp;
121   schnellexpt(2,10,1022);
122}
123
124
125
126
127
128////////////////////////////////////////////////////////////////////////
129
130
131proc schnellexppoly(poly a,number m)
132"USAGE: schnellexppoly(a,m);
133RETURN: the m-th power of poly a
134NOTE:   uses fast exponentiation;
135        proc schnellexp for a poly a instead of a number a;
136EXAMPLE:example schnellexppoly; shows an example
137"
138{
139 number c;
140 poly b,d;
141
142 c=m;
143 b=a;
144 d=1;
145
146  while(c>=1)
147  {
148    if((c mod 2)==1)
149     {
150       d=d*b;
151     }
152
153   b=b^2;
154   c=intPart(c/2);
155
156  }
157 return(d)
158}
159example
160{ "EXAMPLE:"; echo = 2;
161   ring R = 0,x,dp;
162   poly a=3*x3-x2+5;
163   number m=21;
164   schnellexppoly(a,m);
165}
166
167
168
169
170
171
172///////////////////////////////////////////////////////////////
173//                                                           //
174//   GENERAL PROCEDURES                                      //
175//                                                           //
176///////////////////////////////////////////////////////////////
177
178
179
180
181proc log2(number x)
182"USAGE:  log2(x);
183RETURN:  logarithm to basis 2 of x
184NOTE:    calculates the natural logarithm of x with a power-series
185         of the ln, then the basis is changed to 2
186EXAMPLE: example log2; shows an example
187"
188{
189 number b,c,d,t,l,k;
190                                         // log2=logarithmus zur basis 2,
191                                         // log=natuerlicher logarithmus
192 b=100000000000000000000000000000000000000000000000000;
193 c=141421356237309504880168872420969807856967187537695;    // c/b=sqrt(2)
194 d=69314718055994530941723212145817656807550013436026;     // d/b=log(2)
195
196//bringen x zunaechst zwischen 1/sqrt(2) und sqrt(2), so dass Reihe schnell
197//konvergiert, berechnen dann Reihe bis 30. Summanden und letztendlich
198//log2(x)=log(x)/log(2)=(log(x/2^j)+j*log(2))/log(2)  für große x
199//log2(x)=log(x)/log(2)=(log(x*2^j)-j*log(2))/log(2)  für kleine x
200
201number j=0;
202
203if(x<(b/c))
204 {
205
206  while(x<(b/c))
207   {
208    x=x*2;
209    j=j+1;
210   }
211
212  t=(x-1)/(x+1);
213  k=0;
214  l=0;
215  while(k<30)       //fuer  x*2^j wird Reihe bis k-tem Summanden berechnet
216   {
217    l=l+2*schnellexp(t,2*k+1)/(2*k+1);      //l=log(x*2^j) nach k Summanden
218
219    k=k+1;
220   }
221
222
223   return((l*b/d)-j);         //log2(x)=log(x*2^j)/log(2)-j wird ausgegeben
224 }
225
226
227 while(x>(c/b))
228   {
229    x=x/2;
230    j=j+1;
231   }
232
233 t=(x-1)/(x+1);
234 k=0;
235 l=0;
236
237 while(k<30)         //fuer  x/2^j wird Reihe bis k-tem Summanden berechnet
238  {
239   l=l+2*schnellexp(t,2*k+1)/(2*k+1);       //l=log(x/2^j) nach k Summanden
240   k=k+1;
241  }
242
243 return((l*b/d)+j);     //hier wird log2(x)=log(x/2^j)/log(2)+j  ausgegeben
244}
245example
246{ "EXAMPLE:"; echo = 2;
247   ring R = 0,x,dp;
248   log2(1024);
249}
250
251
252
253//////////////////////////////////////////////////////////////////////////
254
255
256proc wurzel(number r)
257"USAGE: wurzel(r);
258ASSUME: caracteristic of basering is 0, r>=0
259RETURN: number, square root of r
260EXAMPLE:example wurzel; shows an example
261"
262{
263 poly f=var(1)^2-r;             //Wurzel wird als Nullstelle eines Polys
264                                //mit proc nt_solve genähert
265
266 def B=basering;
267
268 ring R=(real,40),var(1),dp;
269
270 poly g=imap(B,f);
271 list l=nt_solve(g,1.1);
272 number m=leadcoef(l[1][1]);
273
274 setring B;
275 number m1=imap(R,m);
276 return(m1);
277}
278example
279{ "EXAMPLE:"; echo = 2;
280   ring R = 0,x,dp;
281   wurzel(7629412809180100);
282}
283
284
285
286//////////////////////////////////////////////////////////////////////////
287
288
289proc euler(number r)
290"USAGE: euler(r);
291RETURN: number phi(r), where phi is eulers phi-function
292NOTE:   first r is factorized with proc PollardRho, then phi(r) is
293        calculated with the help of phi(p) of every factor p;
294EXAMPLE:example euler; shows an example
295"
296{
297  list l=PollardRho(r,5000,1);           //bestimmen der Primfaktoren von r
298
299 int k;
300 number phi=r;
301
302   for(k=1;k<=size(l);k++)
303    {
304      phi=phi-phi/l[k];       //berechnen phi(r) mit Hilfe der
305    }                         //Primfaktoren und Eigenschaften der phi-Fktn
306
307 return(phi);
308
309}
310example
311{ "EXAMPLE:"; echo = 2;
312   ring R = 0,x,dp;
313   euler(99991);
314}
315
316
317
318
319
320///////////////////////////////////////////////////////////////
321//                                                           //
322//   PERFECT POWER TEST                                      //
323//                                                           //
324///////////////////////////////////////////////////////////////
325
326
327proc PerfectPowerTest(number n)
328"USAGE: PerfectPowerTest(n);
329RETURN: 0 if there are numbers a,b>1 with a^b=n;
330        1 if there are no numbers a,b>1 with a^b=n;
331        if printlevel>=1 and there are a,b>1 with a^b=n,
332        then a,b are printed
333EXAMPLE:example PerfectPowerTest; shows an example
334"
335{
336  number a,b,c,e,f,m,l,p;
337  b=2;
338  l=log2(n);
339  e=0;
340  f=1;
341
342  while(b<=l)
343   {
344     a=1;
345     c=n;
346
347     while(c-a>=2)
348      {
349        m=intPart((a+c)/2);
350        p=schnellexpt(m,b,n);
351
352        if(p==n)
353          {
354            if(printlevel>=1){"es existieren Zahlen a,b>1 mit a^b=n";
355                          "a=";m;"b=";b;pause();}
356            return(e);
357          }
358
359        if(p<n)
360          {
361            a=m;
362          }
363        else
364          {
365            c=m;
366          }
367      }
368     b=b+1;
369   }
370  if(printlevel>=1){"es existieren keine Zahlen a,b>1  mit a^b=n";pause();}
371  return(f);
372}
373example
374{ "EXAMPLE:"; echo = 2;
375   ring R = 0,x,dp;
376   PerfectPowerTest(887503681);
377}
378
379
380
381
382
383
384
385
386///////////////////////////////////////////////////////////////
387//                                                           //
388//   FAST MODULAR EXPONENTIATION OF POLYNOMIALS              //
389//                                                           //
390///////////////////////////////////////////////////////////////
391
392
393
394proc coeffmod(poly f,number n)
395"USAGE: coeffmod(f,n);
396ASSUME: poly f depends on at most var(1) of the basering
397RETURN: poly f modulo number n
398NOTE:   at first the coefficients of the monomials of the poly f are
399        determined, then their remainder modulo n is calculated,
400        after that the poly 'is put together' again
401EXAMPLE:example coeffmod; shows an example
402"
403{
404  matrix M=coeffs(f,var(1));         //Bestimmung der Polynomkoeffizienten
405  int i=1;
406  poly g;
407  number o=nrows(M);
408
409  while(i<=o)
410    {
411      g=g+(leadcoef(M[i,1]) mod n)*var(1)^(i-1) ;
412                     // umwandeln der Koeffizienten in numbers,
413                     // Berechnung der Reste dieser numbers modulo n,
414                     // poly mit neuen Koeffizienten wieder zusammensetzen
415      i=i+1;
416    }
417  return(g);
418}
419example
420{ "EXAMPLE:"; echo = 2;
421   ring R = 0,x,dp;
422   poly f=2457*x4+52345*x3-98*x2+5;
423   number n=3;
424   coeffmod(f,n);
425}
426
427
428
429
430
431
432
433
434//////////////////////////////////////////////////////////////////////////
435
436
437proc powerpolyX(number q,number n,poly a,poly r)
438"USAGE: powerpolyX(q,n,a,r);
439RETURN: the q-th power of poly a modulo poly r and number n
440EXAMPLE:example powerpolyX; shows an example
441"
442{
443  ideal I=std(r);
444
445   if(q==1){return(coeffmod(reduce(a,I),n));}
446   if((q mod 5)==0){return(coeffmod(reduce(powerpolyX(q/5,n,a,r)^5,I),n));}
447   if((q mod 4)==0){return(coeffmod(reduce(powerpolyX(q/4,n,a,r)^4,I),n));}
448   if((q mod 3)==0){return(coeffmod(reduce(powerpolyX(q/3,n,a,r)^3,I),n));}
449   if((q mod 2)==0){return(coeffmod(reduce(powerpolyX(q/2,n,a,r)^2,I),n));}
450
451  return(coeffmod(reduce(a*powerpolyX(q-1,n,a,r),I),n));
452}
453example
454{ "EXAMPLE:"; echo = 2;
455   ring R=0,x,dp;
456   poly a=3*x3-x2+5;
457   poly r=x7-1;
458   number q=123;
459   number n=5;
460   powerpolyX(q,n,a,r);
461}
462
463
464
465
466///////////////////////////////////////////////////////////////
467//                                                           //
468//   ASK PRIMALITY TEST                                      //
469//                                                           //
470///////////////////////////////////////////////////////////////
471
472
473
474proc ask(number n)
475"USAGE: ask(n);
476ASSUME: n>1
477RETURN: 0 if n is composite;
478        1 if n is prime;
479        if printlevel>=1, you are informed what the procedure will do
480        or has calculated
481NOTE:   ASK-algorithm; uses proc powerpolyX for step 5
482EXAMPLE:example ask; shows an example
483"
484{
485  number c,p;
486  c=0;
487  p=1;
488
489  if(n==2)
490   {
491    return(p);
492   }
493
494
495 if(printlevel>=1){"Beginn: Test ob a^b=n fuer a,b>1";pause();}
496
497 if(0==PerfectPowerTest(n))             // Schritt1 des ASK-Alg.
498   {
499    return(c);
500   }
501
502 if(printlevel>=1)
503 {"Beginn: Berechnung von r, so dass ord(n) in Z/rZ groesser log2(n)^2 ";
504  pause();}
505
506 number k,M,M2,b;
507 int r;                          // Zeile 526-542: Schritt 2
508 M=log2(n);                      // darin sind die Schritte
509 M2=intPart(M^2);                // 3 und 4 integriert
510 r=2;
511
512
513 if(gcdN(n,r)!=1)   //falls ggt ungleich eins, Teiler von n gefunden,
514                    // Schritt 3 des ASK-Alg.
515   {
516    if(printlevel>=1){"Zahl r gefunden mit r|n";"r=";r;pause();}
517    return(c);
518   }
519
520 if(r==n-1)              // falls diese Bedingung erfüllt ist, ist
521                         // ggT(a,n)=1 für 0<a<=r, schritt 4 des ASK-Alg.
522  {
523   if(printlevel>=1){"ggt(r,n)=1 fuer alle 1<r<n";pause();}
524   return(p);
525  }
526
527  k=1;
528  b=1;
529
530  while(k<=M2)         //Beginn des Ordnungstests für aktuelles r
531    {
532           b=((b*n) mod r);
533
534     if(b==1)   //tritt Bedingung ein so gilt für aktuelles r,k:
535                //n^k=1 mod r
536                //tritt Bedingung ein, wird wegen k<=M2=intPart(log2(n)^2)
537                //r erhöht,k=0 gesetzt und Ordnung erneut untersucht
538                //tritt diese Bedingung beim größten k=intPart(log2(n)^2)
539                //nicht ein, so ist ord_r_(n)>log2(n)^2 und Schleife
540                //wird nicht mehr ausgeführt
541      {
542           if(r==2147483647)
543        {
544             string e="error: r überschreitet integer Bereich und darf
545                   nicht als Grad eines Polynoms verwendet werden";
546         return(e);
547        }
548
549       r=r+1;
550
551       if(gcdN(n,r)!=1)   //falls ggt ungleich eins, Teiler von n gefunden,
552                          //wird aufgrund von Schritt 3 des ASK-Alg. für
553                          //jeden Kandidaten r getestet
554         {
555          if(printlevel>=1){"Zahl r gefunden mit r|n";"r=";r;pause();}
556          return(c);
557         }
558
559       if(r==n-1)         //falls diese Bedingung erfüllt ist,
560                          //ist n wegen Zeile 571 prim
561                          //wird aufgrund von Schritt 4 des ASK-Alg. für
562                          //jeden Kandidaten r getestet
563         {
564          if(printlevel>=1){"ggt(r,n)=1 fuer alle 1<r<n";pause();}
565          return(p);
566         }
567
568       k=0;               //für neuen Kandidaten r, muss k für den
569                          //Ordnungstest zurückgesetzt werden
570      }
571
572     k=k+1;
573    }
574
575
576
577 if(printlevel>=1)
578  {"Zahl r gefunden, so dass ord(n) in Z/rZ groesser log2(n)^2 ";
579   "r=";r;pause();}
580
581
582
583 number l=1;                         // Zeile 603-628: Schritt 5
584 poly f,g;                           // Zeile 618 überprüft Gleichungen für
585                                     // das jeweilige a
586 g=var(1)^r-1;
587 number grenze=intPart(wurzel(euler(r))*M);
588
589 if(printlevel>=1)
590 {"Beginn: Ueberpruefung ob (x+a)^n kongruent x^n+a mod (x^r-1,n)
591        fuer 0<a<=intPart(wurzel(phi(r))*log2(n))=";grenze;pause();}
592
593 while(l<=grenze)          //
594   {
595     if(printlevel>=1){"a=";l;}
596     f=var(1)+l;
597
598      if(powerpolyX(n,n,f,g)!=(schnellexppoly(var(1),(n mod r))+l))
599       {
600         if(printlevel>=1)
601          {"Fuer a=";l;"ist (x+a)^n nicht kongruent x^n+a mod (x^r-1,n)";
602            pause();}
603
604         return(c);
605       }
606
607      l=l+1;
608   }
609
610 if(printlevel>=1)
611  {"(x+a)^n kongruent x^n+a mod (x^r-1,n) fuer 0<a<wurzel(phi(r))*log2(n)";
612    pause();}
613
614 return(p);       // Schritt 6
615}
616example
617{ "EXAMPLE:"; echo = 2;
618   ring R = 0,x,dp;
619   ask(100003);
620}
621
622
Note: See TracBrowser for help on using the repository browser.