2021SC@SDUSC 山东大学软件学院软件工程应用与实践
1、mrarth1.c结构
mrath1.c的总体结构如下,,主要实现了big_to_bytes()、bytes_to_big()、hamming()、mr_invert()、mr_jsf()、mr_pmul()、mr_sdiv()、premult()、remain()、subdiv()、subdivisible()几个在miracl开源库中比较重要的函数,这一次的博客就是读一下这函数的功能。
2、源代码
mr_large mr_invert(mr_small n)
{
mr_large inn;
int up= 0x1BFF;
#ifdef _MSC_VER
#ifdef MR_NOASM
#define NO_EXTENDED
#endif
#endif
#ifdef NO_EXTENDED
int down=0x1EFF;
#else
int down=0x1FFF;
#endif
#ifdef __TURBOC__
asm
{
fldcw WORD PTR up
fld1
fld QWORD PTR n;
fdiv
fstp TBYTE PTR inn;
fldcw WORD PTR down;
}
return inn;
#endif
#ifdef _MSC_VER
_asm
{
fldcw WORD PTR up
fld1
fld QWORD PTR n;
fdiv
fstp QWORD PTR inn;
fldcw WORD PTR down;
}
return inn;
#endif
#ifdef __GNUC__
#ifdef i386
__asm__ __volatile__ (
"fldcw %2\n"
"fld1\n"
"fldl %1\n"
"fdivrp\n"
"fstpt %0\n"
"fldcw %3\n"
: "=m"(inn)
: "m"(n),"m"(up),"m"(down)
: "memory"
);
return inn;
#else
fpsetround(FP_RP);
inn=(mr_large)1.0/n;
fpsetround(FP_RZ);
return inn;
#endif
#endif
return 0.0L;
}
#endif
mr_invert()方法的主要作用就是将一个mr_small类型的数据n(即无符号整数)强制转换为mr_large类型的数据(即long long类型数据)。
void mr_pmul(_MIPD_ big x,mr_small sn,big z)
{
int m,xl;
mr_lentype sx;
mr_small carry,*xg,*zg;
#ifdef MR_ITANIUM
mr_small tm;
#endif
#ifdef MR_WIN64
mr_small tm;
#endif
#ifdef MR_NOASM
union doubleword dble;
mr_large dbled;
mr_large ldres;
#endif
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (x!=z)
{
zero(z);
if (sn==0) return;
}
else if (sn==0)
{
zero(z);
return;
}
m=0;
carry=0;
sx=x->len&MR_MSBIT;
xl=(int)(x->len&MR_OBITS);
#ifndef MR_SIMPLE_BASE
if (mr_mip->base==0)
{
#endif
#ifndef MR_NOFULLWIDTH
xg=x->w; zg=z->w;
/* inline 8086 assembly - substitutes for loop below */
#ifdef INLINE_ASM
#if INLINE_ASM == 1
ASM cld
ASM mov cx,xl
ASM or cx,cx
ASM je out1
#ifdef MR_LMM
ASM push ds
ASM push es
ASM les di,DWORD PTR zg
ASM lds si,DWORD PTR xg
#else
ASM mov ax,ds
ASM mov es,ax
ASM mov di,zg
ASM mov si,xg
#endif
ASM mov bx,sn
ASM push bp
ASM xor bp,bp
tcl1:
ASM lodsw
ASM mul bx
ASM add ax,bp
ASM adc dx,0
ASM stosw
ASM mov bp,dx
ASM loop tcl1
ASM mov ax,bp
ASM pop bp
#ifdef MR_LMM
ASM pop es
ASM pop ds
#endif
ASM mov carry,ax
out1:
#endif
#if INLINE_ASM == 2
ASM cld
ASM mov cx,xl
ASM or cx,cx
ASM je out1
#ifdef MR_LMM
ASM push ds
ASM push es
ASM les di,DWORD PTR zg
ASM lds si,DWORD PTR xg
#else
ASM mov ax,ds
ASM mov es,ax
ASM mov di,zg
ASM mov si,xg
#endif
ASM mov ebx,sn
ASM push ebp
ASM xor ebp,ebp
tcl1:
ASM lodsd
ASM mul ebx
ASM add eax,ebp
ASM adc edx,0
ASM stosd
ASM mov ebp,edx
ASM loop tcl1
ASM mov eax,ebp
ASM pop ebp
#ifdef MR_LMM
ASM pop es
ASM pop ds
#endif
ASM mov carry,eax
out1:
#endif
#if INLINE_ASM == 3
ASM mov ecx,xl
ASM or ecx,ecx
ASM je out1
ASM mov ebx,sn
ASM mov edi,zg
ASM mov esi,xg
ASM push ebp
ASM xor ebp,ebp
tcl1:
ASM mov eax,[esi]
ASM add esi,4
ASM mul ebx
ASM add eax,ebp
ASM adc edx,0
ASM mov [edi],eax
ASM add edi,4
ASM mov ebp,edx
ASM dec ecx
ASM jnz tcl1
ASM mov eax,ebp
ASM pop ebp
ASM mov carry,eax
out1:
#endif
#if INLINE_ASM == 4
ASM (
"movl %4,%%ecx\n"
"orl %%ecx,%%ecx\n"
"je 1f\n"
"movl %3,%%ebx\n"
"movl %1,%%edi\n"
"movl %2,%%esi\n"
"pushl %%ebp\n"
"xorl %%ebp,%%ebp\n"
"0:\n"
"movl (%%esi),%%eax\n"
"addl $4,%%esi\n"
"mull %%ebx\n"
"addl %%ebp,%%eax\n"
"adcl $0,%%edx\n"
"movl %%eax,(%%edi)\n"
"addl $4,%%edi\n"
"movl %%edx,%%ebp\n"
"decl %%ecx\n"
"jnz 0b\n"
"movl %%ebp,%%eax\n"
"popl %%ebp\n"
"movl %%eax,%0\n"
"1:"
:"=m"(carry)
:"m"(zg),"m"(xg),"m"(sn),"m"(xl)
:"eax","edi","esi","ebx","ecx","edx","memory"
);
#endif
#endif
#ifndef INLINE_ASM
for (m=0;m<xl;m++)
#ifdef MR_NOASM
{
dble.d=(mr_large)x->w[m]*sn+carry;
carry=dble.h[MR_TOP];
z->w[m]=dble.h[MR_BOT];
}
#else
carry=muldvd(x->w[m],sn,carry,&z->w[m]);
#endif
#endif
if (carry>0)
{
m=xl;
if (m>=mr_mip->nib && mr_mip->check)
{
mr_berror(_MIPP_ MR_ERR_OVERFLOW);
return;
}
z->w[m]=carry;
z->len=m+1;
}
else z->len=xl;
#endif
#ifndef MR_SIMPLE_BASE
}
else while (m<xl || carry>0)
{ /* multiply each digit of x by n */
if (m>mr_mip->nib && mr_mip->check)
{
mr_berror(_MIPP_ MR_ERR_OVERFLOW);
return;
}
#ifdef MR_NOASM
dbled=(mr_large)x->w[m]*sn+carry;
#ifdef MR_FP_ROUNDING
carry=(mr_small)MR_LROUND(dbled*mr_mip->inverse_base);
#else
#ifndef MR_FP
if (mr_mip->base==mr_mip->base2)
carry=(mr_small)(dbled>>mr_mip->lg2b);
else
#endif
carry=(mr_small)MR_LROUND(dbled/mr_mip->base);
#endif
z->w[m]=(mr_small)(dbled-(mr_large)carry*mr_mip->base);
#else
#ifdef MR_FP_ROUNDING
carry=imuldiv(x->w[m],sn,carry,mr_mip->base,mr_mip->inverse_base,&z->w[m]);
#else
carry=muldiv(x->w[m],sn,carry,mr_mip->base,&z->w[m]);
#endif
#endif
m++;
z->len=m;
}
#endif
if (z->len!=0) z->len|=sx;
}
mr_pmul()方法的主要作用就是把一个大数字乘以一个整数。先判断x和z是否相等,再调用zero方法清空z的属性。然后把x的w[i]和sn相乘,最后观察是否需要进位。
void premult(_MIPD_ big x,int n,big z)
{ /* premultiply a big number by an int z=x.n */
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
MR_IN(9)
#ifdef MR_FLASH
if (mr_notint(x))
{
mr_berror(_MIPP_ MR_ERR_INT_OP);
MR_OUT
return;
}
#endif
if (n==0) /* test for some special cases */
{
zero(z);
MR_OUT
return;
}
if (n==1)
{
copy(x,z);
MR_OUT
return;
}
if (n<0)
{
n=(-n);
mr_pmul(_MIPP_ x,(mr_small)n,z);
if (z->len!=0) z->len^=MR_MSBIT;
}
else mr_pmul(_MIPP_ x,(mr_small)n,z);
MR_OUT
}
premult()方法的主要作用就是把一个大数字乘以一个整数。首先根据n的值决定调用zero()方法清空z、调用copy()亦或mr_pmul()进行常规乘法。
mr_small mr_sdiv(_MIPD_ big x,mr_small sn,big z)
#endif
{
int i,xl;
mr_small sr,*xg,*zg;
#ifdef MR_NOASM
union doubleword dble;
mr_large dbled;
mr_large ldres;
#endif
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
sr=0;
xl=(int)(x->len&MR_OBITS);
if (x!=z) zero(z);
#ifndef MR_SIMPLE_BASE
if (mr_mip->base==0)
{
#endif
#ifndef MR_NOFULLWIDTH
xg=x->w; zg=z->w;
/* inline - substitutes for loop below */
#ifdef INLINE_ASM
#if INLINE_ASM == 1
ASM std
ASM mov cx,xl
ASM or cx,cx
ASM je out2
ASM mov bx,cx
ASM shl bx,1
ASM sub bx,2
#ifdef MR_LMM
ASM push ds
ASM push es
ASM les di,DWORD PTR zg
ASM lds si,DWORD PTR xg
#else
ASM mov ax,ds
ASM mov es,ax
ASM mov di,zg
ASM mov si,xg
#endif
ASM add si,bx
ASM add di,bx
ASM mov bx,sn
ASM push bp
ASM xor bp,bp
tcl2:
ASM mov dx,bp
ASM lodsw
ASM div bx
ASM mov bp,dx
ASM stosw
ASM loop tcl2
ASM mov ax,bp
ASM pop bp
#ifdef MR_LMM
ASM pop es
ASM pop ds
#endif
ASM mov sr,ax
out2:
ASM cld
#endif
#if INLINE_ASM == 2
ASM std
ASM mov cx,xl
ASM or cx,cx
ASM je out2
ASM mov bx,cx
ASM shl bx,2
ASM sub bx,4
#ifdef MR_LMM
ASM push ds
ASM push es
ASM les di,DWORD PTR zg
ASM lds si,DWORD PTR xg
#else
ASM mov ax,ds
ASM mov es,ax
ASM mov di, zg
ASM mov si, xg
#endif
ASM add si,bx
ASM add di,bx
ASM mov ebx,sn
ASM push ebp
ASM xor ebp,ebp
tcl2:
ASM mov edx,ebp
ASM lodsd
ASM div ebx
ASM mov ebp,edx
ASM stosd
ASM loop tcl2
ASM mov eax,ebp
ASM pop ebp
#ifdef MR_LMM
ASM pop es
ASM pop ds
#endif
ASM mov sr,eax
out2:
ASM cld
#endif
#if INLINE_ASM == 3
ASM mov ecx,xl
ASM or ecx,ecx
ASM je out2
ASM mov ebx,ecx
ASM shl ebx,2
ASM mov esi, xg
ASM add esi,ebx
ASM mov edi, zg
ASM add edi,ebx
ASM mov ebx,sn
ASM push ebp
ASM xor ebp,ebp
tcl2:
ASM sub esi,4
ASM mov edx,ebp
ASM mov eax,[esi]
ASM div ebx
ASM sub edi,4
ASM mov ebp,edx
ASM mov [edi],eax
ASM dec ecx
ASM jnz tcl2
ASM mov eax,ebp
ASM pop ebp
ASM mov sr,eax
out2:
ASM nop
#endif
#if INLINE_ASM == 4
ASM (
"movl %4,%%ecx\n"
"orl %%ecx,%%ecx\n"
"je 3f\n"
"movl %%ecx,%%ebx\n"
"shll $2,%%ebx\n"
"movl %2,%%esi\n"
"addl %%ebx,%%esi\n"
"movl %1,%%edi\n"
"addl %%ebx,%%edi\n"
"movl %3,%%ebx\n"
"pushl %%ebp\n"
"xorl %%ebp,%%ebp\n"
"2:\n"
"subl $4,%%esi\n"
"movl %%ebp,%%edx\n"
"movl (%%esi),%%eax\n"
"divl %%ebx\n"
"subl $4,%%edi\n"
"movl %%edx,%%ebp\n"
"movl %%eax,(%%edi)\n"
"decl %%ecx\n"
"jnz 2b\n"
"movl %%ebp,%%eax\n"
"popl %%ebp\n"
"movl %%eax,%0\n"
"3:"
"nop"
:"=m"(sr)
:"m"(zg),"m"(xg),"m"(sn),"m"(xl)
:"eax","edi","esi","ebx","ecx","edx","memory"
);
#endif
#endif
#ifndef INLINE_ASM
for (i=xl-1;i>=0;i--)
{
#ifdef MR_NOASM
dble.h[MR_BOT]=x->w[i];
dble.h[MR_TOP]=sr;
z->w[i]=(mr_small)(dble.d/sn);
sr=(mr_small)(dble.d-(mr_large)z->w[i]*sn);
#else
z->w[i]=muldvm(sr,x->w[i],sn,&sr);
#endif
}
#endif
#endif
#ifndef MR_SIMPLE_BASE
}
else for (i=xl-1;i>=0;i--)
{ /* divide each digit of x by n */
#ifdef MR_NOASM
dbled=(mr_large)sr*mr_mip->base+x->w[i];
#ifdef MR_FP_ROUNDING
z->w[i]=(mr_small)MR_LROUND(dbled*isn);
#else
z->w[i]=(mr_small)MR_LROUND(dbled/sn);
#endif
sr=(mr_small)(dbled-(mr_large)z->w[i]*sn);
#else
#ifdef MR_FP_ROUNDING
z->w[i]=imuldiv(sr,mr_mip->base,x->w[i],sn,isn,&sr);
#else
z->w[i]=muldiv(sr,mr_mip->base,x->w[i],sn,&sr);
#endif
#endif
}
#endif
z->len=x->len;
mr_lzero(z);
return sr;
}
mr_sdiv()方法的主要作用就是把一个大数字除以一个整数。首先把x复制给z,再把w[i]都除以n,最后看是否需要退位。
int subdiv(_MIPD_ big x,int n,big z)
{ /* subdivide a big number by an int z=x/n *
* returns int remainder */
mr_lentype sx;
#ifdef MR_FP_ROUNDING
mr_large in;
#endif
int r,i,msb;
mr_small lsb;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return 0;
MR_IN(10)
#ifdef MR_FLASH
if (mr_notint(x)) mr_berror(_MIPP_ MR_ERR_INT_OP);
#endif
if (n==0) mr_berror(_MIPP_ MR_ERR_DIV_BY_ZERO);
if (mr_mip->ERNUM)
{
MR_OUT
return 0;
}
if (x->len==0)
{
zero(z);
MR_OUT
return 0;
}
if (n==1) /* special case */
{
copy(x,z);
MR_OUT
return 0;
}
sx=(x->len&MR_MSBIT);
if (n==2 && mr_mip->base==0)
{ /* fast division by 2 using shifting */
#ifndef MR_NOFULLWIDTH
/* I don't want this code upsetting the compiler ... */
/* mr_mip->base==0 can't happen with MR_NOFULLWIDTH */
copy(x,z);
msb=(int)(z->len&MR_OBITS)-1;
r=(int)z->w[0]&1;
for (i=0;;i++)
{
z->w[i]>>=1;
if (i==msb)
{
if (z->w[i]==0) mr_lzero(z);
break;
}
lsb=z->w[i+1]&1;
z->w[i]|=(lsb<<(MIRACL-1));
}
MR_OUT
if (sx==0) return r;
else return (-r);
#endif
}
#ifdef MR_FP_ROUNDING
in=mr_invert(n);
#endif
if (n<0)
{
n=(-n);
#ifdef MR_FP_ROUNDING
r=(int)mr_sdiv(_MIPP_ x,(mr_small)n,in,z);
#else
r=(int)mr_sdiv(_MIPP_ x,(mr_small)n,z);
#endif
if (z->len!=0) z->len^=MR_MSBIT;
}
#ifdef MR_FP_ROUNDING
else r=(int)mr_sdiv(_MIPP_ x,(mr_small)n,in,z);
#else
else r=(int)mr_sdiv(_MIPP_ x,(mr_small)n,z);
#endif
MR_OUT
if (sx==0) return r;
else return (-r);
}
subdiv()方法的主要作用就是把一个大数字除以一个整数获得一个余数。首先看n是否为1或2,是1的话调用copy()方法把x复制给z,是2的话使用移位法快速除以2得到结果。非特殊情况下先定义copy()方法,再把z的w[i]全部右移一位,然后看w[i]是否需要退位,循环要结束是看w[i]是否为零选择调用mr_lzero()方法从大数字中去掉前导零。或者根据不同情况选择调用mr_sdiv()方法。
int remain(_MIPD_ big x,int n)
{ /* return integer remainder when x divided by n */
int r;
mr_lentype sx;
#ifdef MR_FP
mr_small dres;
#endif
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return FALSE;
MR_IN(88);
sx=(x->len&MR_MSBIT);
if (n==2 && MR_REMAIN(mr_mip->base,2)==0)
{ /* fast odd/even check if base is even */
MR_OUT
if ((int)MR_REMAIN(x->w[0],2)==0) return 0;
else
{
if (sx==0) return 1;
else return (-1);
}
}
if (n==8 && MR_REMAIN(mr_mip->base,8)==0)
{ /* fast check */
MR_OUT
r=(int)MR_REMAIN(x->w[0],8);
if (sx!=0) r=-r;
return r;
}
copy(x,mr_mip->w0);
r=subdiv(_MIPP_ mr_mip->w0,n,mr_mip->w0);
MR_OUT
return r;
}
remain()方法的主要作用就是获得一个大数字除以一个整数之后的余数。首先查看n=2或者8的天数情况,如果不是2或者8的话调用subdiv()方法求余数。
BOOL subdivisible(_MIPD_ big x,int n)
{
if (remain(_MIPP_ x,n)==0) return TRUE;
else return FALSE;
}
subdivsible()方法的主要作用就是看一个大数字是否能被一个整数整除。
int hamming(_MIPD_ big x)
{
int h;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return 0;
MR_IN(148);
h=0;
copy(x,mr_mip->w1);
absol(mr_mip->w1,mr_mip->w1);
while (size(mr_mip->w1)!=0)
h+=subdiv(_MIPP_ mr_mip->w1,2,mr_mip->w1);
MR_OUT
return h;
}
hamming()方法的主要作用就是计算一个大数字的二进制表示中1的数量。通过调用subdiv()方法计算余数之和。
void bytes_to_big(_MIPD_ int len,const char *ptr,big x)
{ /* convert len bytes into a big *
* The first byte is the Most significant */
int i,j,m,n,r;
unsigned int dig;
unsigned char ch;
mr_small wrd;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
MR_IN(140);
zero(x);
if (len<=0)
{
MR_OUT
return;
}
/* remove leading zeros.. */
while (*ptr==0)
{
ptr++; len--;
if (len==0)
{
MR_OUT
return;
}
}
#ifndef MR_SIMPLE_BASE
if (mr_mip->base==0)
{ /* pack bytes directly into big */
#endif
#ifndef MR_NOFULLWIDTH
m=MIRACL/8;
n=len/m;
r=len%m;
wrd=(mr_small)0;
if (r!=0)
{
n++;
for (j=0;j<r;j++) {wrd<<=8; wrd|=MR_TOBYTE(*ptr++); }
}
x->len=n;
if (n>mr_mip->nib && mr_mip->check)
{
mr_berror(_MIPP_ MR_ERR_OVERFLOW);
MR_OUT
return;
}
if (r!=0)
{
n--;
x->w[n]=wrd;
}
for (i=n-1;i>=0;i--)
{
for (j=0;j<m;j++) { wrd<<=8; wrd|=MR_TOBYTE(*ptr++); }
x->w[i]=wrd;
}
mr_lzero(x); /* needed */
#endif
#ifndef MR_SIMPLE_BASE
}
else
{
for (i=0;i<len;i++)
{
if (mr_mip->ERNUM) break;
#if MIRACL==8
mr_shift(_MIPP_ x,1,x);
#else
premult(_MIPP_ x,256,x);
#endif
ch=MR_TOBYTE(ptr[i]);
dig=ch;
incr(_MIPP_ x,(int)dig,x);
}
}
#endif
MR_OUT
}
bytes_to_big()方法的主要作用就是把一长串字符转化为大数字。
int big_to_bytes(_MIPD_ int max,big x,char *ptr,BOOL justify)
{ /* convert positive big into octet string */
int i,j,r,m,n,len,start;
unsigned int dig;
unsigned char ch;
mr_small wrd;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM || max<0) return 0;
if (max==0 && justify) return 0;
if (size(x)==0)
{
if (justify)
{
for (i=0;i<max;i++) ptr[i]=0;
return max;
}
return 0;
}
MR_IN(141);
mr_lzero(x); /* should not be needed.... */
#ifndef MR_SIMPLE_BASE
if (mr_mip->base==0)
{
#endif
#ifndef MR_NOFULLWIDTH
m=MIRACL/8;
n=(int)(x->len&MR_OBITS);
n--;
len=n*m;
wrd=x->w[n]; /* most significant */
r=0;
while (wrd!=(mr_small)0) { r++; wrd>>=8; len++;}
r%=m;
if (max>0 && len>max)
{
mr_berror(_MIPP_ MR_ERR_TOO_BIG);
MR_OUT
return 0;
}
if (justify)
{
start=max-len;
for (i=0;i<start;i++) ptr[i]=0;
}
else start=0;
if (r!=0)
{
wrd=x->w[n--];
for (i=r-1;i>=0;i--)
{
ptr[start+i]=(char)(wrd&0xFF);
wrd>>=8;
}
}
for (i=r;i<len;i+=m)
{
wrd=x->w[n--];
for (j=m-1;j>=0;j--)
{
ptr[start+i+j]=(char)(wrd&0xFF);
wrd>>=8;
}
}
#endif
#ifndef MR_SIMPLE_BASE
}
else
{
copy(x,mr_mip->w1);
for (len=0;;len++)
{
if (mr_mip->ERNUM) break;
if (size(mr_mip->w1)==0)
{
if (justify)
{
if (len==max) break;
}
else break;
}
if (max>0 && len>=max)
{
mr_berror(_MIPP_ MR_ERR_TOO_BIG);
MR_OUT
return 0;
}
#if MIRACL==8
ch=mr_mip->w1->w[0];
mr_shift(_MIPP_ mr_mip->w1,-1,mr_mip->w1);
#else
dig=(unsigned int)subdiv(_MIPP_ mr_mip->w1,256,mr_mip->w1);
ch=MR_TOBYTE(dig);
#endif
for (i=len;i>0;i--) ptr[i]=ptr[i-1];
ptr[0]=MR_TOBYTE(ch);
}
}
#endif
MR_OUT
if (justify) return max;
else return len;
}
big_to_bytes()方法的主要作用就是把一个大数字转化为一个8进制的字符串。
void mr_jsf(_MIPD_ big k0,big k1,big u0p,big u0m,big u1p,big u1m)
{
int j,u0,u1,d0,d1,l0,l1;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
if (mr_mip->ERNUM) return;
MR_IN(191)
d0=d1=0;
convert(_MIPP_ 1,mr_mip->w1);
copy(k0,mr_mip->w2);
copy(k1,mr_mip->w3);
zero(u0p); zero(u0m); zero(u1p); zero(u1m);
j=0;
while (!mr_mip->ERNUM)
{
if (size(mr_mip->w2)==0 && d0==0 && size(mr_mip->w3)==0 && d1==0) break;
l0=remain(_MIPP_ mr_mip->w2,8);
l0=(l0+d0)&0x7;
l1=remain(_MIPP_ mr_mip->w3,8);
l1=(l1+d1)&0x7;
if (l0%2==0) u0=0;
else
{
u0=2-(l0%4);
if ((l0==3 || l0==5) && l1%4==2) u0=-u0;
}
if (l1%2==0) u1=0;
else
{
u1=2-(l1%4);
if ((l1==3 || l1==5) && l0%4==2) u1=-u1;
}
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base==mr_mip->base2)
{
#endif
if (u0>0) mr_addbit(_MIPP_ u0p,j);
if (u0<0) mr_addbit(_MIPP_ u0m,j);
if (u1>0) mr_addbit(_MIPP_ u1p,j);
if (u1<0) mr_addbit(_MIPP_ u1m,j);
#ifndef MR_ALWAYS_BINARY
}
else
{
if (u0>0) add(_MIPP_ u0p,mr_mip->w1,u0p);
if (u0<0) add(_MIPP_ u0m,mr_mip->w1,u0m);
if (u1>0) add(_MIPP_ u1p,mr_mip->w1,u1p);
if (u1<0) add(_MIPP_ u1m,mr_mip->w1,u1m);
}
#endif
if (d0+d0==1+u0) d0=1-d0;
if (d1+d1==1+u1) d1=1-d1;
subdiv(_MIPP_ mr_mip->w2,2,mr_mip->w2);
subdiv(_MIPP_ mr_mip->w3,2,mr_mip->w3);
#ifndef MR_ALWAYS_BINARY
if (mr_mip->base==mr_mip->base2)
#endif
j++;
#ifndef MR_ALWAYS_BINARY
else
premult(_MIPP_ mr_mip->w1,2,mr_mip->w1);
#endif
}
MR_OUT
return;
}
mr_jsf()方法的主要实现了由Solinas提出的联合稀疏形式(JSF)。它以加速椭圆曲线密码系统中的多标量乘法而闻名。