home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_200
/
247_01
/
bnsmall.c
< prev
next >
Wrap
Text File
|
1989-04-19
|
4KB
|
183 lines
/*
* MIRACL small number theoretic routines
* bnsmall.c
*/
#include <stdio.h>
#include <math.h>
#include "miracl.h"
/* access global variables */
extern int depth; /* error tracing... */
extern int trace[]; /* ....mechanism */
extern char *calloc();
int *gprime(maxp)
int maxp;
{ /* generate all primes less than maxp */
int *primes;
double dn;
char *sv;
int pix,i,k,prime;
if (ERNUM) return NULL;
if (maxp<0)
{ /* generate (-maxp) primes */
dn=(-maxp);
if (dn<20.0) dn=20.0;
maxp=(int)(dn*(log(dn*log(dn))-0.5)); /* Rossers upper bound */
}
depth++;
trace[depth]=70;
if (TRACER) track();
if (maxp>=TOOBIG)
{
berror(8);
depth--;
return NULL;
}
maxp=(maxp+1)/2;
sv=(char *)calloc(maxp,1);
if (sv==NULL)
{
berror(8);
depth--;
return NULL;
}
pix=1;
for (i=0;i<maxp;i++)
sv[i]=TRUE;
for (i=0;i<maxp;i++)
if (sv[i])
{ /* using sieve of Eratosthenes */
prime=i+i+3;
for (k=i+prime;k<maxp;k+=prime)
sv[k]=FALSE;
pix++;
}
primes=(int *)calloc(pix+2,sizeof(int));
if (primes==NULL)
{
berror(8);
depth--;
return NULL;
}
primes[0]=2;
pix=1;
for (i=0;i<maxp;i++)
if (sv[i]) primes[pix++]=i+i+3;
primes[pix]=0;
free(sv);
depth--;
return primes;
}
small smul(x,y,n)
small x,y,n;
{ /* returns x*y mod n */
small r;
x%=n;
y%=n;
if (x<0) x+=n;
if (y<0) y+=n;
muldiv(x,y,(small)0,n,&r);
return r;
}
small spmd(x,n,m)
small x,n,m;
{ /* returns x^n mod m */
small r;
x%=m;
if (x<0) x+=m;
r=0;
if (x==0) return r;
r=1;
if (n==0) return r;
forever
{
if (n%2!=0) muldiv(r,x,(small)0,m,&r);
n/=2;
if (n==0) return r;
muldiv(x,x,(small)0,m,&x);
}
}
small inverse(x,y)
small x,y;
{ /* returns inverse of x mod y */
small r,s,q,t,p;
x%=y;
if (x<0) x+=y;
r=1;
s=0;
p=y;
while (p!=0)
{ /* main euclidean loop */
q=x/p;
t=r-s*q;
r=s;
s=t;
t=x-p*q;
x=p;
p=t;
}
if (r<0) r+=y;
return r;
}
small sqrmp(x,m)
small x,m;
{ /* square root mod a small prime by Shanks method *
* returns 0 if root does not exist or m not prime */
small q,z,y,v,w,t;
int i,r,e,n;
bool pp;
x%=m;
if (x==0) return 0;
if (x<0) x+=m;
if (x==1) return 1;
if (spmd(x,(m-1)/2,m)!=1) return 0; /* Legendre symbol not 1 */
if (m%4==3) return spmd(x,(m+1)/4,m); /* easy case for m=4.k+3 */
q=m-1;
e=0;
while (q%2==0)
{
q/=2;
e++;
}
if (e==0) return 0; /* even m */
for (r=2;;r++)
{ /* find suitable z */
z=spmd((small)r,q,m);
if (z==1) continue;
t=z;
pp=FALSE;
for (i=1;i<e;i++)
{ /* check for composite m */
if (t==(m-1)) pp=TRUE;
muldiv(t,t,(small)0,m,&t);
if (t==1 && !pp) return 0;
}
if (t==(m-1)) break;
if (!pp) return 0; /* m is not prime */
}
y=z;
r=e;
v=spmd(x,(q+1)/2,m);
w=spmd(x,q,m);
while (w!=1)
{
t=w;
for (n=0;t!=1;n++) muldiv(t,t,(small)0,m,&t);
if (n>=r) return 0;
y=spmd(y,(small)(1<<(r-n-1)),m);
muldiv(v,y,(small)0,m,&v);
muldiv(y,y,(small)0,m,&y);
muldiv(w,y,(small)0,m,&w);
r=n;
}
return v;
}