📄 mrsmall.c
字号:
/*
* MIRACL small number theoretic routines
* mrsmall.c
*
* Copyright (c) 1988-1997 Shamus Software Ltd.
*/
#include <stdio.h>
#include "miracl.h"
mr_small smul(mr_small x,mr_small y,mr_small n)
{ /* returns x*y mod n */
mr_small r;
#ifdef MR_ITANIUM
mr_small tm;
#endif
#ifdef MR_FP
mr_small dres;
#endif
#ifndef MR_NOFULLWIDTH
if (n==0)
{ /* Assume n=2^MIRACL */
muldvd(x,y,(mr_small)0,&r);
return r;
}
#endif
x=MR_REMAIN(x,n);
y=MR_REMAIN(y,n);
muldiv(x,y,(mr_small)0,n,&r);
return r;
}
mr_small spmd(mr_small x,mr_small n,mr_small m)
{ /* returns x^n mod m */
mr_small r,sx;
#ifdef MR_FP
mr_small dres;
#endif
x=MR_REMAIN(x,m);
r=0;
if (x==0) return r;
r=1;
if (n==0) return r;
sx=x;
forever
{
if (MR_REMAIN(n,2)!=0) muldiv(r,sx,(mr_small)0,m,&r);
n=MR_DIV(n,2);
if (n==0) return r;
muldiv(sx,sx,(mr_small)0,m,&sx);
}
}
mr_small invers(mr_small x,mr_small y)
{ /* returns inverse of x mod y */
mr_small r,s,q,t,p;
#ifdef MR_FP
mr_small dres;
#endif
BOOL pos;
if (y!=0) x=MR_REMAIN(x,y);
r=1;
s=0;
p=y;
pos=TRUE;
#ifndef MR_NOFULLWIDTH
if (p==0)
{ /* if modulus is 0, assume its actually 2^MIRACL */
if (x==1) return (mr_small)1;
t=r; r=s; s=t;
p=x;
q=muldvm((mr_small)1,(mr_small)0,p,&t);
t=r+s*q; r=s; s=t;
t=0-p*q; x=p; p=t;
}
#endif
while (p!=0)
{ /* main euclidean loop */
q=MR_DIV(x,p);
t=r+s*q; r=s; s=t;
t=x-p*q; x=p; p=t;
pos=!pos;
}
if (!pos) r=y-r;
return r;
}
mr_small sqrmp(mr_small x,mr_small m)
{ /* square root mod a small prime by Shanks method *
* returns 0 if root does not exist or m not prime */
mr_small z,y,v,w,t,q;
#ifdef MR_FP
mr_small dres;
#endif
int i,e,n,r;
BOOL pp;
x=MR_REMAIN(x,m);
if (x==0) return 0;
if (x==1) return 1;
if (spmd(x,(mr_small)((m-1)/2),m)!=1) return 0; /* Legendre symbol not 1 */
if (MR_REMAIN(m,4)==3) return spmd(x,(mr_small)((m+1)/4),m); /* easy case for m=4.k+3 */
if (MR_REMAIN(m,8)==5)
{ /* also relatively easy */
t=spmd(x,(mr_small)((m-1)/4),m);
if (t==1) return spmd(x,(mr_small)((m+3)/8),m);
if (t==(mr_small)(m-1))
{
muldiv((mr_small)4,x,(mr_small)0,m,&t);
t=spmd(t,(mr_small)((m+3)/8),m);
muldiv(t,(mr_small)((m+1)/2),(mr_small)0,m,&t);
return t;
}
return 0;
}
q=m-1;
e=0;
while (MR_REMAIN(q,2)==0)
{
q=MR_DIV(q,2);
e++;
}
if (e==0) return 0; /* even m */
for (r=2;;r++)
{ /* find suitable z */
z=spmd((mr_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,(mr_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,(mr_small)((q+1)/2),m);
w=spmd(x,q,m);
while (w!=1)
{
t=w;
for (n=0;t!=1;n++) muldiv(t,t,(mr_small)0,m,&t);
if (n>=r) return 0;
y=spmd(y,mr_shiftbits(1,r-n-1),m);
muldiv(v,y,(mr_small)0,m,&v);
muldiv(y,y,(mr_small)0,m,&y);
muldiv(w,y,(mr_small)0,m,&w);
r=n;
}
return v;
}
int jac(mr_small x,mr_small n)
{ /* finds (x/n) as (-1)^m */
int m,k,n8,u4;
mr_small t;
#ifdef MR_FP
mr_small dres;
#endif
if (x==0)
{
if (n==1) return 1;
else return 0;
}
if (MR_REMAIN(n,2)==0) return 0;
x=MR_REMAIN(x,n);
m=0;
while(n>1)
{ /* main loop */
if (x==0) return 0;
/* extract powers of 2 */
for (k=0;MR_REMAIN(x,2)==0;k++) x=MR_DIV(x,2);
n8=MR_REMAIN(n,8);
if (k%2==1) m+=(n8*n8-1)/8;
/* quadratic reciprocity */
u4=MR_REMAIN(x,4);
m+=(n8-1)*(u4-1)/4;
t=n; t=MR_REMAIN(t,x);
n=x; x=t;
m%=2;
}
if (m==0) return 1;
else return (-1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -