📄 mrpower.c
字号:
#endif
if (mr_mip->ERNUM) return;
MR_IN(79)
prepare_monty(_MIPP_ n);
nres(_MIPP_ x,mr_mip->w2);
nres(_MIPP_ a,mr_mip->w4);
nres_powmod2(_MIPP_ mr_mip->w2,y,mr_mip->w4,b,w);
redc(_MIPP_ w,w);
MR_OUT
}
void powmod(_MIPD_ big x,big y,big n,big w)
{ /* fast powmod, using Montgomery's method internally */
mr_small norm;
BOOL mty;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
MR_IN(18)
mty=TRUE;
if (mr_mip->base!=mr_mip->base2)
{
if (size(n)<2 || sgcd(n->w[0],mr_mip->base)!=1) mty=FALSE;
}
else
if (subdivisible(_MIPP_ n,2)) mty=FALSE;
if (!mty)
{ /* can't use Montgomery */
copy(y,mr_mip->w1);
copy(x,mr_mip->w3);
zero(w);
if (size(mr_mip->w3)==0)
{
MR_OUT
return;
}
convert(_MIPP_ 1,w);
if (size(mr_mip->w1)==0)
{
MR_OUT
return;
}
if (size(mr_mip->w1)<0) mr_berror(_MIPP_ MR_ERR_NEG_POWER);
if (w==n) mr_berror(_MIPP_ MR_ERR_BAD_PARAMETERS) ;
if (mr_mip->ERNUM)
{
MR_OUT
return;
}
norm=normalise(_MIPP_ n,n);
divide(_MIPP_ mr_mip->w3,n,n);
forever
{
if (mr_mip->user!=NULL) (*mr_mip->user)();
if (subdiv(_MIPP_ mr_mip->w1,2,mr_mip->w1)!=0)
mad(_MIPP_ w,mr_mip->w3,mr_mip->w3,n,n,w);
if (mr_mip->ERNUM || size(mr_mip->w1)==0) break;
mad(_MIPP_ mr_mip->w3,mr_mip->w3,mr_mip->w3,n,n,mr_mip->w3);
}
if (norm!=1)
{
#ifdef MR_FP_ROUNDING
mr_sdiv(_MIPP_ n,norm,mr_invert(norm),n);
#else
mr_sdiv(_MIPP_ n,norm,n);
#endif
divide(_MIPP_ w,n,n);
}
}
else
{ /* optimized code for odd moduli */
prepare_monty(_MIPP_ n);
nres(_MIPP_ x,mr_mip->w3);
nres_powmod(_MIPP_ mr_mip->w3,y,w);
redc(_MIPP_ w,w);
}
MR_OUT
}
int powltr(_MIPD_ int x, big y, big n, big w)
{
mr_small norm;
BOOL clean_up,mty;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return 0;
MR_IN(71)
mty=TRUE;
if (mr_mip->base!=mr_mip->base2)
{
if (size(n)<2 || sgcd(n->w[0],mr_mip->base)!=1) mty=FALSE;
}
else
{
if (subdivisible(_MIPP_ n,2)) mty=FALSE;
}
/* Is Montgomery modulus in use... */
clean_up=FALSE;
if (mty)
{ /* still a chance to use monty... */
if (mr_mip->modulus!=NULL)
{ /* somebody else is using it */
if (compare(n,mr_mip->modulus)!=0) mty=FALSE;
}
else
{ /* its unused, so use it, but clean up after */
clean_up=TRUE;
}
}
if (!mty)
{ /* can't use Montgomery! */
copy(y,mr_mip->w1);
zero(w);
if (x==0)
{
MR_OUT
return 0;
}
convert(_MIPP_ 1,w);
if (size(mr_mip->w1)==0)
{
MR_OUT
return 1;
}
if (size(mr_mip->w1)<0) mr_berror(_MIPP_ MR_ERR_NEG_POWER);
if (w==n) mr_berror(_MIPP_ MR_ERR_BAD_PARAMETERS) ;
if (mr_mip->ERNUM)
{
MR_OUT
return 0;
}
norm=normalise(_MIPP_ n,n);
expb2(_MIPP_ logb2(_MIPP_ mr_mip->w1)-1,mr_mip->w2);
while (size(mr_mip->w2)!=0)
{ /* Left to Right binary method */
if (mr_mip->user!=NULL) (*mr_mip->user)();
if (mr_mip->ERNUM) break;
mad(_MIPP_ w,w,w,n,n,w);
if (compare(mr_mip->w1,mr_mip->w2)>=0)
{
premult(_MIPP_ w,x,w);
divide(_MIPP_ w,n,n);
subtract(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w1);
}
subdiv(_MIPP_ mr_mip->w2,2,mr_mip->w2);
}
if (norm!=1)
{
#ifdef MR_FP_ROUNDING
mr_sdiv(_MIPP_ n,norm,mr_invert(norm),n);
#else
mr_sdiv(_MIPP_ n,norm,n);
#endif
divide(_MIPP_ w,n,n);
}
}
else
{ /* optimized code for odd moduli */
prepare_monty(_MIPP_ n);
nres_powltr(_MIPP_ x,y,w);
redc(_MIPP_ w,w);
if (clean_up) kill_monty(_MIPPO_ );
}
MR_OUT
return (size(w));
}
void nres_powmod(_MIPD_ big x,big y,big w)
{ /* calculates w=x^y mod z, using m-residues *
* See "Analysis of Sliding Window Techniques for *
* Exponentiation, C.K. Koc, Computers. Math. & *
* Applic. Vol. 30 pp17-24 1995. Uses work-space *
* variables for pre-computed table. */
int i,j,k,t,nb,nbw,nzs,n;
big table[16];
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
copy(y,mr_mip->w1);
copy(x,mr_mip->w3);
MR_IN(84)
zero(w);
if (size(x)==0)
{
if (size(mr_mip->w1)==0)
{ /* 0^0 = 1 */
convert(_MIPP_ 1,w);
nres(_MIPP_ w,w);
}
MR_OUT
return;
}
convert(_MIPP_ 1,w);
nres(_MIPP_ w,w);
if (size(mr_mip->w1)==0)
{
MR_OUT
return;
}
if (size(mr_mip->w1)<0) mr_berror(_MIPP_ MR_ERR_NEG_POWER);
if (mr_mip->ERNUM)
{
MR_OUT
return;
}
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base==mr_mip->base2)
{ /* build a table. Up to 5-bit sliding windows. Windows with
* two adjacent 0 bits simply won't happen */
#endif
table[0]=mr_mip->w3; table[1]=mr_mip->w4; table[2]=mr_mip->w5; table[3]=mr_mip->w16;
table[4]=NULL; table[5]=mr_mip->w6; table[6]=mr_mip->w17; table[7]=mr_mip->w8;
table[8]=NULL; table[9]=NULL; table[10]=mr_mip->w9; table[11]=mr_mip->w10;
table[12]=NULL; table[13]=mr_mip->w11; table[14]=mr_mip->w12; table[15]=mr_mip->w13;
nres_modmult(_MIPP_ mr_mip->w3,mr_mip->w3,mr_mip->w2); /* x^2 */
n=15;
j=0;
do
{ /* pre-computations */
t=1; k=j+1;
while (table[k]==NULL) {k++; t++;}
copy(table[j],table[k]);
for (i=0;i<t;i++) nres_modmult(_MIPP_ table[k],mr_mip->w2,table[k]);
j=k;
} while (j<n);
nb=logb2(_MIPP_ mr_mip->w1);
copy(mr_mip->w3,w);
if (nb>1) for (i=nb-2;i>=0;)
{ /* Left to Right method */
if (mr_mip->user!=NULL) (*mr_mip->user)();
n=mr_window(_MIPP_ mr_mip->w1,i,&nbw,&nzs);
for (j=0;j<nbw;j++)
nres_modmult(_MIPP_ w,w,w);
if (n>0) nres_modmult(_MIPP_ w,table[n/2],w);
i-=nbw;
if (nzs)
{
for (j=0;j<nzs;j++) nres_modmult(_MIPP_ w,w,w);
i-=nzs;
}
}
#ifndef MR_ALWAYS_BINARY
}
else
{
copy(mr_mip->w3,mr_mip->w2);
forever
{ /* "Russian peasant" Right-to-Left exponentiation */
if (mr_mip->user!=NULL) (*mr_mip->user)();
if (subdiv(_MIPP_ mr_mip->w1,2,mr_mip->w1)!=0)
nres_modmult(_MIPP_ w,mr_mip->w2,w);
if (mr_mip->ERNUM || size(mr_mip->w1)==0) break;
nres_modmult(_MIPP_ mr_mip->w2,mr_mip->w2,mr_mip->w2);
}
}
#endif
MR_OUT
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -