source: git/Singular/LIB/aksaka.lib @ 334c21f

fieker-DuValspielwiese
Last change on this file since 334c21f was 1a3911, checked in by Frank Seelisch <seelisch@…>, 15 years ago
removed some docu errors prior to release 3-1-0 git-svn-id: file:///usr/local/Singular/svn/trunk@11626 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 12.1 KB
RevLine 
[449fbf]1//CM, last modified 10.12.06
2///////////////////////////////////////////////////////////////////////////////
[1a3911]3version="$Id: aksaka.lib,v 1.4 2009-04-06 12:39:02 seelisch Exp $";
[449fbf]4category="Teaching";
5info="
[1a3911]6LIBRARY: aksaka.lib     Procedures for primality testing after Agrawal, Saxena, Kayal
[449fbf]7AUTHORS: Christoph Mang
8
[1a3911]9OVERVIEW:
[449fbf]10 Algorithms for primality testing in polynomial time
11 based on the ideas of Agrawal, Saxena and  Kayal.
12
13PROCEDURES:
14
[1a3911]15fastExpt(a,m,n)         a^m for numbers a,m; if a^k>n n+1 is returned
[449fbf]16log2(n)                    logarithm to basis 2 of n
17PerfectPowerTest(n)        checks if there are a,b>1, so that a^b=n
18wurzel(r)                  square root of number r
19euler(r)                   phi-function of euler
20coeffmod(f,n)              poly f modulo number n (coefficients mod n)
21powerpolyX(q,n,a,r)        (poly a)^q modulo (poly r,number n)
22ask(n)                     ASK-Algorithm; deterministic Primality test
23";
24
[abb4919]25LIB "crypto.lib";
[449fbf]26LIB "ntsolve.lib";
27
28///////////////////////////////////////////////////////////////
29//                                                           //
[f3a11a]30//   FAST (MODULAR) EXPONENTIATION                           //
[449fbf]31//                                                           //
[abb4919]32///////////////////////////////////////////////////////////////
[1a3911]33proc fastExpt(number a,number m,number n)
34"USAGE: fastExpt(a,m,n); a, m, n = number;
[449fbf]35RETURN: the m-th power of a; if a^m>n the procedure returns n+1
36NOTE:   uses fast exponentiation
[1a3911]37EXAMPLE:example fastExpt; shows an example
[449fbf]38"
39{
[226c28]40  number b,c,d;
41  c=m;
42  b=a;
43  d=1;
[449fbf]44  while(c>=1)
45  {
[226c28]46    if(b>n)
47    {
[449fbf]48      return(n+1);
[226c28]49    }
[449fbf]50    if((c mod 2)==1)
[226c28]51    {
52      d=d*b;
53      if(d>n)
54      {
55        return(n+1);
56      }
57    }
58    b=b^2;
59    c=intPart(c/2);
[449fbf]60  }
[226c28]61  return(d)
[449fbf]62}
63example
64{ "EXAMPLE:"; echo = 2;
65   ring R = 0,x,dp;
[1a3911]66   fastExpt(2,10,1022);
[449fbf]67}
[f3a11a]68////////////////////////////////////////////////////////////////////////////
69proc coeffmod(poly f,number n)
[abb4919]70"USAGE: coeffmod(f,n);
[f3a11a]71ASSUME: poly f depends on at most var(1) of the basering
[abb4919]72RETURN: poly f modulo number n
73NOTE:   at first the coefficients of the monomials of the poly f are
74        determined, then their remainder modulo n is calculated,
75        after that the poly 'is put together' again
[f3a11a]76EXAMPLE:example coeffmod; shows an example
[449fbf]77"
[abb4919]78{
[f3a11a]79  matrix M=coeffs(f,var(1));         //Bestimmung der Polynomkoeffizienten
80  int i=1;
81  poly g;
[226c28]82  int o=nrows(M);
[449fbf]83
[f3a11a]84  while(i<=o)
[226c28]85  {
86    g=g+(leadcoef(M[i,1]) mod n)*var(1)^(i-1) ;
87                   // umwandeln der Koeffizienten in numbers,
88                   // Berechnung der Reste dieser numbers modulo n,
89                   // poly mit neuen Koeffizienten wieder zusammensetzen
90    i++;
91  }
[f3a11a]92  return(g);
[449fbf]93}
94example
[abb4919]95{ "EXAMPLE:"; echo = 2;
[449fbf]96   ring R = 0,x,dp;
[f3a11a]97   poly f=2457*x4+52345*x3-98*x2+5;
98   number n=3;
99   coeffmod(f,n);
[abb4919]100}
[f3a11a]101//////////////////////////////////////////////////////////////////////////
102proc powerpolyX(number q,number n,poly a,poly r)
[abb4919]103"USAGE: powerpolyX(q,n,a,r);
104RETURN: the q-th power of poly a modulo poly r and number n
[f3a11a]105EXAMPLE:example powerpolyX; shows an example
106"
107{
[226c28]108  ideal I=r;
[abb4919]109
[226c28]110  if(q==1){return(coeffmod(reduce(a,I),n));}
111  if((q mod 5)==0){return(coeffmod(reduce(powerpolyX(q/5,n,a,r)^5,I),n));}
112  if((q mod 4)==0){return(coeffmod(reduce(powerpolyX(q/4,n,a,r)^4,I),n));}
113  if((q mod 3)==0){return(coeffmod(reduce(powerpolyX(q/3,n,a,r)^3,I),n));}
114  if((q mod 2)==0){return(coeffmod(reduce(powerpolyX(q/2,n,a,r)^2,I),n));}
[f3a11a]115
116  return(coeffmod(reduce(a*powerpolyX(q-1,n,a,r),I),n));
[abb4919]117}
[f3a11a]118example
[abb4919]119{ "EXAMPLE:"; echo = 2;
[f3a11a]120   ring R=0,x,dp;
[449fbf]121   poly a=3*x3-x2+5;
[f3a11a]122   poly r=x7-1;
123   number q=123;
124   number n=5;
125   powerpolyX(q,n,a,r);
[449fbf]126}
127///////////////////////////////////////////////////////////////
128//                                                           //
129//   GENERAL PROCEDURES                                      //
130//                                                           //
131///////////////////////////////////////////////////////////////
132proc log2(number x)
133"USAGE:  log2(x);
134RETURN:  logarithm to basis 2 of x
135NOTE:    calculates the natural logarithm of x with a power-series
136         of the ln, then the basis is changed to 2
137EXAMPLE: example log2; shows an example
138"
139{
[226c28]140  number b,c,d,t,l;
141  int k;
[449fbf]142                                         // log2=logarithmus zur basis 2,
143                                         // log=natuerlicher logarithmus
[226c28]144  b=100000000000000000000000000000000000000000000000000;
145  c=141421356237309504880168872420969807856967187537695;    // c/b=sqrt(2)
146  d=69314718055994530941723212145817656807550013436026;     // d/b=log(2)
[449fbf]147
[226c28]148  //bringen x zunaechst zwischen 1/sqrt(2) und sqrt(2), so dass Reihe schnell
149  //konvergiert, berechnen dann Reihe bis 30. Summanden und letztendlich
150  //log2(x)=log(x)/log(2)=(log(x/2^j)+j*log(2))/log(2)  für große x
151  //log2(x)=log(x)/log(2)=(log(x*2^j)-j*log(2))/log(2)  für kleine x
[449fbf]152
[226c28]153  number j=0;
154  if(x<(b/c))
155  {
156    while(x<(b/c))
157    {
158      x=x*2;
159      j=j+1;
160    }
161    t=(x-1)/(x+1);
162    k=0;
163    l=0;
164    while(k<30)       //fuer  x*2^j wird Reihe bis k-tem Summanden berechnet
165    {
166      l=l+2*(t^(2*k+1))/(2*k+1);      //l=log(x*2^j) nach k Summanden
167      k=k+1;
168    }
169    return((l*b/d)-j);         //log2(x)=log(x*2^j)/log(2)-j wird ausgegeben
170  }
171  while(x>(c/b))
172  {
173    x=x/2;
[449fbf]174    j=j+1;
[226c28]175  }
[449fbf]176  t=(x-1)/(x+1);
177  k=0;
178  l=0;
[226c28]179  while(k<30)         //fuer  x/2^j wird Reihe bis k-tem Summanden berechnet
[449fbf]180  {
[226c28]181    l=l+2*(t^(2*k+1))/(2*k+1);       //l=log(x/2^j) nach k Summanden
182    k=k+1;
[449fbf]183  }
[226c28]184  return((l*b/d)+j);     //hier wird log2(x)=log(x/2^j)/log(2)+j  ausgegeben
[449fbf]185}
186example
187{ "EXAMPLE:"; echo = 2;
188   ring R = 0,x,dp;
189   log2(1024);
190}
191//////////////////////////////////////////////////////////////////////////
192proc wurzel(number r)
193"USAGE: wurzel(r);
[d2f488]194ASSUME: characteristic of basering is 0, r>=0
[449fbf]195RETURN: number, square root of r
196EXAMPLE:example wurzel; shows an example
197"
198{
[226c28]199  poly f=var(1)^2-r;             //Wurzel wird als Nullstelle eines Polys
200                                 //mit proc nt_solve genähert
201  def B=basering;
202  ring R=(real,40),var(1),dp;
203  poly g=imap(B,f);
204  list l=nt_solve(g,1.1);
205  number m=leadcoef(l[1][1]);
206  setring B;
207  return(imap(R,m));
[449fbf]208}
209example
210{ "EXAMPLE:"; echo = 2;
211   ring R = 0,x,dp;
212   wurzel(7629412809180100);
213}
214//////////////////////////////////////////////////////////////////////////
215proc euler(number r)
216"USAGE: euler(r);
217RETURN: number phi(r), where phi is eulers phi-function
218NOTE:   first r is factorized with proc PollardRho, then phi(r) is
219        calculated with the help of phi(p) of every factor p;
220EXAMPLE:example euler; shows an example
221"
222{
223  list l=PollardRho(r,5000,1);           //bestimmen der Primfaktoren von r
[226c28]224  int k;
225  number phi=r;
226  for(k=1;k<=size(l);k++)
227  {
228    phi=phi-phi/l[k];       //berechnen phi(r) mit Hilfe der
229  }                         //Primfaktoren und Eigenschaften der phi-Fktn
230  return(phi);
[449fbf]231}
232example
233{ "EXAMPLE:"; echo = 2;
234   ring R = 0,x,dp;
235   euler(99991);
236}
237///////////////////////////////////////////////////////////////
238//                                                           //
239//   PERFECT POWER TEST                                      //
240//                                                           //
241///////////////////////////////////////////////////////////////
242proc PerfectPowerTest(number n)
243"USAGE: PerfectPowerTest(n);
244RETURN: 0 if there are numbers a,b>1 with a^b=n;
245        1 if there are no numbers a,b>1 with a^b=n;
246        if printlevel>=1 and there are a,b>1 with a^b=n,
247        then a,b are printed
248EXAMPLE:example PerfectPowerTest; shows an example
249"
250{
251  number a,b,c,e,f,m,l,p;
252  b=2;
253  l=log2(n);
254  e=0;
255  f=1;
256
257  while(b<=l)
[226c28]258  {
259    a=1;
260    c=n;
[449fbf]261
[226c28]262    while(c-a>=2)
263    {
264      m=intPart((a+c)/2);
[1a3911]265      p=fastExpt(m,b,n);
[449fbf]266
[226c28]267      if(p==n)
268      {
269        if(printlevel>=1){"es existieren Zahlen a,b>1 mit a^b=n";
270                      "a=";m;"b=";b;pause();}
271        return(e);
272      }
[449fbf]273
[226c28]274      if(p<n)
275      {
276        a=m;
[449fbf]277      }
[226c28]278      else
279      {
280        c=m;
281      }
282    }
283    b=b+1;
284  }
[449fbf]285  if(printlevel>=1){"es existieren keine Zahlen a,b>1  mit a^b=n";pause();}
286  return(f);
287}
288example
289{ "EXAMPLE:"; echo = 2;
290   ring R = 0,x,dp;
291   PerfectPowerTest(887503681);
292}
293///////////////////////////////////////////////////////////////
294//                                                           //
295//   ASK PRIMALITY TEST                                      //
296//                                                           //
297///////////////////////////////////////////////////////////////
298proc ask(number n)
299"USAGE: ask(n);
300ASSUME: n>1
301RETURN: 0 if n is composite;
302        1 if n is prime;
303        if printlevel>=1, you are informed what the procedure will do
304        or has calculated
305NOTE:   ASK-algorithm; uses proc powerpolyX for step 5
306EXAMPLE:example ask; shows an example
307"
308{
309  number c,p;
310  c=0;
311  p=1;
312
[226c28]313  if(n==2) { return(p); }
314  if(printlevel>=1){"Beginn: Test ob a^b=n fuer a,b>1";pause();}
315  if(0==PerfectPowerTest(n))             // Schritt1 des ASK-Alg.
316  { return(c); }
317  if(printlevel>=1)
318  {
319    "Beginn: Berechnung von r, so dass ord(n) in Z/rZ groesser log2(n)^2 ";
320    pause();
321  }
322  number k,M,M2,b;
323  int r;                          // Zeile 526-542: Schritt 2
324  M=log2(n);                      // darin sind die Schritte
325  M2=intPart(M^2);                // 3 und 4 integriert
326  r=2;
[449fbf]327
[226c28]328  if(gcdN(n,r)!=1)   //falls ggt ungleich eins, Teiler von n gefunden,
[449fbf]329                    // Schritt 3 des ASK-Alg.
[226c28]330  {
[449fbf]331    if(printlevel>=1){"Zahl r gefunden mit r|n";"r=";r;pause();}
332    return(c);
[226c28]333  }
334  if(r==n-1)              // falls diese Bedingung erfüllt ist, ist
[449fbf]335                         // ggT(a,n)=1 für 0<a<=r, schritt 4 des ASK-Alg.
336  {
[226c28]337    if(printlevel>=1){"ggt(r,n)=1 fuer alle 1<r<n";pause();}
338    return(p);
[449fbf]339  }
340  k=1;
341  b=1;
342
343  while(k<=M2)         //Beginn des Ordnungstests für aktuelles r
[226c28]344  {
345    b=((b*n) mod r);
346    if(b==1)   //tritt Bedingung ein so gilt für aktuelles r,k:
347               //n^k=1 mod r
348               //tritt Bedingung ein, wird wegen k<=M2=intPart(log2(n)^2)
349               //r erhöht,k=0 gesetzt und Ordnung erneut untersucht
350               //tritt diese Bedingung beim größten k=intPart(log2(n)^2)
351               //nicht ein, so ist ord_r_(n)>log2(n)^2 und Schleife
352               //wird nicht mehr ausgeführt
[449fbf]353    {
[226c28]354      if(r==2147483647)
[449fbf]355      {
[226c28]356        string e="error: r überschreitet integer Bereich und darf
357                  nicht als Grad eines Polynoms verwendet werden";
358        return(e);
359      }
360      r=r+1;
361      if(gcdN(n,r)!=1)   //falls ggt ungleich eins, Teiler von n gefunden,
362                         //wird aufgrund von Schritt 3 des ASK-Alg. für
363                         //jeden Kandidaten r getestet
364      {
365        if(printlevel>=1){"Zahl r gefunden mit r|n";"r=";r;pause();}
366        return(c);
367      }
368      if(r==n-1)         //falls diese Bedingung erfüllt ist,
369                         //ist n wegen Zeile 571 prim
370                         //wird aufgrund von Schritt 4 des ASK-Alg. für
371                         //jeden Kandidaten r getestet
372      {
373        if(printlevel>=1){"ggt(r,n)=1 fuer alle 1<r<n";pause();}
374        return(p);
[449fbf]375      }
376
[226c28]377      k=0;               //für neuen Kandidaten r, muss k für den
378                         //Ordnungstest zurückgesetzt werden
[449fbf]379    }
[226c28]380    k=k+1;
381  }
382  if(printlevel>=1)
383  {
384    "Zahl r gefunden, so dass ord(n) in Z/rZ groesser log2(n)^2 ";
385    "r=";r;pause();
386  }
387  number l=1;                         // Zeile 603-628: Schritt 5
388  poly f,g;                           // Zeile 618 überprüft Gleichungen für
389                                      // das jeweilige a
390  g=var(1)^r-1;
391  number grenze=intPart(wurzel(euler(r))*M);
392
393  if(printlevel>=1)
394  {"Beginn: Ueberpruefung ob (x+a)^n kongruent x^n+a mod (x^r-1,n)
395        fuer 0<a<=intPart(wurzel(phi(r))*log2(n))=";grenze;pause();
396  }
397  while(l<=grenze)          //
398  {
399    if(printlevel>=1){"a=";l;}
400    f=var(1)+l;
401    if(powerpolyX(n,n,f,g)!=(var(1)^(int((n mod r)))+l))
402    {
403      if(printlevel>=1)
404      {"Fuer a=";l;"ist (x+a)^n nicht kongruent x^n+a mod (x^r-1,n)";
405        pause();
406      }
407      return(c);
408    }
409    l=l+1;
410  }
411  if(printlevel>=1)
[449fbf]412  {"(x+a)^n kongruent x^n+a mod (x^r-1,n) fuer 0<a<wurzel(phi(r))*log2(n)";
[226c28]413    pause();
414  }
415  return(p);       // Schritt 6
[449fbf]416}
417example
418{ "EXAMPLE:"; echo = 2;
419   ring R = 0,x,dp;
[f3a11a]420   //ask(100003);
421   ask(32003);
[449fbf]422}
Note: See TracBrowser for help on using the repository browser.