KGC_TEST/miracl/source/pollard.c

172 lines
5.0 KiB
C

/*
* Program to factor big numbers using Pollards (p-1) method.
* Works when for some prime divisor p of n, p-1 has itself
* only small factors.
* See "Speeding the Pollard and Elliptic Curve Methods"
* by Peter Montgomery, Math. Comp. Vol. 48 Jan. 1987 pp243-264
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "miracl.h"
#define LIMIT1 10000 /* must be int, and > MULT/2 */
#define LIMIT2 1000000L /* may be long */
#define MULT 2310 /* must be int, product of small primes 2.3.. */
#define NEXT 13 /* next small prime */
miracl *mip;
static BOOL plus[1+MULT/2],minus[1+MULT/2];
void marks(long start)
{ /* mark non-primes in this interval. Note *
* that those < NEXT are dealt with already */
int i,pr,j,k;
for (j=1;j<=MULT/2;j+=2) plus[j]=minus[j]=TRUE;
for (i=0;;i++)
{ /* mark in both directions */
pr=mip->PRIMES[i];
if (pr<NEXT) continue;
if ((long)pr*pr>start) break;
k=pr-start%pr;
for (j=k;j<=MULT/2;j+=pr)
plus[j]=FALSE;
k=start%pr;
for (j=k;j<=MULT/2;j+=pr)
minus[j]=FALSE;
}
}
int main()
{ /* factoring program using Pollards (p-1) method */
long i,p,pa,interval;
big n,t,b,bw,bvw,bd,bp,q;
static big bu[1+MULT/2];
static BOOL cp[1+MULT/2];
int phase,m,pos,btch,iv;
mip=mirsys(30,0);
n=mirvar(0);
t=mirvar(0);
b=mirvar(0);
q=mirvar(0);
bw=mirvar(0);
bvw=mirvar(0);
bd=mirvar(0);
bp=mirvar(0);
gprime(LIMIT1);
for (m=1;m<=MULT/2;m+=2)
if (igcd(MULT,m)==1)
{
bu[m]=mirvar(0);
cp[m]=TRUE;
}
else cp[m]=FALSE;
printf("input number to be factored\n");
cinnum(n,stdin);
if (isprime(n))
{
printf("this number is prime!\n");
return 0;
}
phase=1;
p=0;
btch=50;
i=0;
convert(2,b); /* if "degenerate case" comes up (see below) try 3 */
printf("phase 1 - trying all primes less than %d\n",LIMIT1);
printf("prime= %8ld",p);
forever
{
if (phase==1)
{ /* looking for all factors of (p-1) < LIMIT1 */
p=mip->PRIMES[i];
if (mip->PRIMES[i+1]==0)
{
phase=2;
printf("\nphase 2 - trying last prime less than %ld\n"
,LIMIT2);
printf("prime= %8ld",p);
power(b,8,n,bw);
convert(1,t);
copy(b,bp);
copy(b,bu[1]);
for (m=3;m<=MULT/2;m+=2)
{ /* store bu[m] = b^(m*m) */
mad(t,bw,bw,n,n,t);
mad(bp,t,t,n,n,bp);
if (cp[m]) copy(bp,bu[m]);
}
power(b,MULT,n,t);
power(t,MULT,n,t);
mad(t,t,t,n,n,bd); /* bd=b^(2*MULT*MULT) */
iv=(int)(p/MULT);
if (p%MULT>MULT/2) iv++;
interval=(long)iv*MULT;
p=interval+1;
marks(interval);
power(t,2*iv-1,n,bw);
power(t,iv,n,bvw);
power(bvw,iv,n,bvw); /* bvw = b^(MULT*MULT*iv*iv) */
subtract(bvw,bu[p%MULT],q);
btch*=100;
i++;
continue;
}
pa=p;
while ((LIMIT1/p) > pa) pa*=p;
power(b,(int)pa,n,b);
decr(b,1,q);
}
else
{ /* looking for last prime factor of (p-1) < LIMIT2 */
p+=2;
pos=(int)(p%MULT);
if (pos>MULT/2)
{ /* increment giant step */
iv++;
interval=(long)iv*MULT;
p=interval+1;
marks(interval);
pos=1;
mad(bw,bd,bd,n,n,bw);
mad(bvw,bw,bw,n,n,bvw);
}
if (!cp[pos]) continue;
/* if neither interval+/-pos is prime, don't bother */
if (!plus[pos] && !minus[pos]) continue;
subtract(bvw,bu[pos],t);
mad(q,t,t,n,n,q); /* batching gcds */
}
if (i++%btch==0)
{ /* try for a solution */
printf("\b\b\b\b\b\b\b\b%8ld",p);
fflush(stdout);
egcd(q,n,t);
if (size(t)==1)
{
if (p>LIMIT2) break;
else continue;
}
if (mr_compare(t,n)==0)
{
printf("\ndegenerate case");
break;
}
printf("\nfactors are\n");
if (isprime(t)) printf("prime factor ");
else printf("composite factor ");
cotnum(t,stdout);
divide(n,t,n);
if (isprime(n)) printf("prime factor ");
else printf("composite factor ");
cotnum(n,stdout);
return 0;
}
}
printf("\nfailed to factor\n");
return 0;
}