2021SC@SDUSC
mrpower.c实现模幂的MIRACL方法。
void nres_powltr(_MIPD_ int x,big y,big w)
{ /* calculates w=x^y mod z using Left to Right Method */
/* uses only n^2 modular squarings, because x is small */
/* Note: x is NOT an nresidue */
int i,nb;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
copy(y,mr_mip->w1);
MR_IN(86)
zero(w);
if (x==0)
{
if (size(mr_mip->w1)==0)
{ /* 0^0 = 1 */
copy(mr_mip->one,w);
}
MR_OUT
return;
}
copy(mr_mip->one,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)
{
#endif
nb=logb2(_MIPP_ mr_mip->w1);
convert(_MIPP_ x,w);
nres(_MIPP_ w,w);
if (nb>1) for (i=nb-2;i>=0;i--)
{ /* Left to Right binary method */
if (mr_mip->user!=NULL) (*mr_mip->user)();
nres_modmult(_MIPP_ w,w,w);
if (mr_testbit(_MIPP_ mr_mip->w1,i))
{ /* this is quick */
premult(_MIPP_ w,x,w);
divide(_MIPP_ w,mr_mip->modulus,mr_mip->modulus);
}
}
#ifndef MR_ALWAYS_BINARY
}
else
{
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;
nres_modmult(_MIPP_ w,w,w);
if (mr_compare(mr_mip->w1,mr_mip->w2)>=0)
{
premult(_MIPP_ w,x,w);
divide(_MIPP_ w,mr_mip->modulus,mr_mip->modulus);
subtract(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w1);
}
subdiv(_MIPP_ mr_mip->w2,2,mr_mip->w2);
}
}
#endif
if (size(w)<0) add(_MIPP_ w,mr_mip->modulus,w);
MR_OUT
return;
}
使用从左到右的方法计算w=xy mod z,且只使用n2模平方
void powmodn(_MIPD_ int n,big *x,big *y,big p,big w)
{/* w=x[0]^y[0].x[1]^y[1] .... x[n-1]^y[n-1] mod n */
int j;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
MR_IN(113)
prepare_monty(_MIPP_ p);
for (j=0;j<n;j++) nres(_MIPP_ x[j],x[j]);
nres_powmodn(_MIPP_ n,x,y,w);
for (j=0;j<n;j++) redc(_MIPP_ x[j],x[j]);
redc(_MIPP_ w,w);
MR_OUT
}
计算数组中所有数的模n