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_WIN64 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 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; }
void frand(_MIPD_ flash x) { /* generates random flash number 0<x<1 */ int i; #ifdef MR_FP mr_small dres; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(46) zero(mr_mip->w6); mr_mip->w6->len=mr_mip->nib; for (i=0;i<mr_mip->nib;i++) { /* generate a full width random number */ if (mr_mip->base==0) mr_mip->w6->w[i]=brand(_MIPPO_ ); else mr_mip->w6->w[i]=MR_REMAIN(brand(_MIPPO_ ),mr_mip->base); } mr_mip->check=OFF; bigrand(_MIPP_ mr_mip->w6,mr_mip->w5); mr_mip->check=ON; mround(_MIPP_ mr_mip->w5,mr_mip->w6,x); MR_OUT }
void strong_bigrand(_MIPD_ csprng *rng,big w,big x) { int i, m; mr_small r; unsigned int ran; unsigned int ch; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; MR_IN(20) m = 0; zero(mr_mip->w1); do { m++; mr_mip->w1->len=m; for (r = 0, i = 0; i < sizeof(mr_small); i++) { ch=(unsigned char)strong_rng(rng); ran=ch; r = (r << 8) ^ ran; } if (mr_mip->base==0) mr_mip->w1->w[m-1]=r; else mr_mip->w1->w[m-1]=MR_REMAIN(r,mr_mip->base); } while (mr_compare(mr_mip->w1,w)<0); mr_lzero(mr_mip->w1); divide(_MIPP_ mr_mip->w1,w,w); copy(mr_mip->w1,x); MR_OUT }
void uconvert(_MIPD_ unsigned int n ,big x) { /* convert integer n to big number format */ int m; #ifdef MR_FP mr_small dres; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zero(x); if (n==0) return; m=0; if (mr_mip->base==0) { #ifndef MR_NOFULLWIDTH #if MR_IBITS > MIRACL while (n>0) { x->w[m++]=(mr_small)(n%((mr_small)1<<(MIRACL))); n/=((mr_small)1<<(MIRACL)); } #else x->w[m++]=(mr_small)n; #endif #endif } else while (n>0) { x->w[m++]=MR_REMAIN((mr_small)n,mr_mip->base); n/=mr_mip->base; } x->len=(m); }
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); } }
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=(int)MR_REMAIN(n,8); if (k%2==1) m+=(n8*n8-1)/8; /* quadratic reciprocity */ u4=(int)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); }
void lgconv(_MIPD_ long n,big x) { /* convert long integer to big number format - rarely needed */ int m; mr_unsign32 s; #ifdef MR_FP mr_small dres; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zero(x); if (n==0) return; s=0; if (n<0) { s=MR_MSBIT; n=(-n); } m=0; if (mr_mip->base==0) { #ifndef MR_NOFULLWIDTH #if MR_LBITS > MIRACL while (n>0) { x->w[m++]=(mr_small)(n%(1L<<(MIRACL))); n/=(1L<<(MIRACL)); } #else x->w[m++]=(mr_small)n; #endif #endif } else while (n>0) { x->w[m++]=MR_REMAIN(n,mr_mip->base); n/=mr_mip->base; } x->len=(m|s); }
void dlconv(_MIPD_ mr_dltype n,big x) { /* convert double length integer to big number format - rarely needed */ int m; mr_unsign32 s; #ifdef MR_FP mr_small dres; #endif #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif zero(x); if (n==0) return; s=0; if (n<0) { s=MR_MSBIT; n=(-n); } m=0; if (mr_mip->base==0) { #ifndef MR_NOFULLWIDTH while (n>0) { x->w[m++]=(mr_small)(n%((mr_dltype)1<<(MIRACL))); n/=((mr_dltype)1<<(MIRACL)); } #endif } else while (n>0) { x->w[m++]=(mr_small)MR_REMAIN(n,mr_mip->base); n/=mr_mip->base; } x->len=(m|s); }
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 egcd(_MIPD_ big x,big y,big z) { /* greatest common divisor z=gcd(x,y) by Euclids * * method using Lehmers algorithm for big numbers */ int q,r,a,b,c,d,n; mr_small sr,m,sm; mr_small u,v,lq,lr; #ifdef MR_FP mr_small dres; #endif big t; #ifndef MR_GENERIC_MT miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return 0; MR_IN(12) copy(x,mr_mip->w1); copy(y,mr_mip->w2); insign(PLUS,mr_mip->w1); insign(PLUS,mr_mip->w2); a=b=c=d=0; while (size(mr_mip->w2)!=0) { if (b==0) { /* update w1 and w2 */ divide(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w2); t=mr_mip->w1,mr_mip->w1=mr_mip->w2,mr_mip->w2=t; /* swap(w1,w2) */ } else { premult(_MIPP_ mr_mip->w1,c,z); premult(_MIPP_ mr_mip->w1,a,mr_mip->w1); premult(_MIPP_ mr_mip->w2,b,mr_mip->w0); premult(_MIPP_ mr_mip->w2,d,mr_mip->w2); add(_MIPP_ mr_mip->w1,mr_mip->w0,mr_mip->w1); add(_MIPP_ mr_mip->w2,z,mr_mip->w2); } if (mr_mip->ERNUM || size(mr_mip->w2)==0) break; n=(int)mr_mip->w1->len; if (mr_mip->w2->len==1) { /* special case if mr_mip->w2 is now small */ sm=mr_mip->w2->w[0]; #ifdef MR_FP_ROUNDING sr=mr_sdiv(_MIPP_ mr_mip->w1,sm,mr_invert(sm),mr_mip->w1); #else sr=mr_sdiv(_MIPP_ mr_mip->w1,sm,mr_mip->w1); #endif if (sr==0) { copy(mr_mip->w2,mr_mip->w1); break; } zero(mr_mip->w1); mr_mip->w1->len=1; mr_mip->w1->w[0]=sr; while ((sr=MR_REMAIN(mr_mip->w2->w[0],mr_mip->w1->w[0]))!=0) mr_mip->w2->w[0]=mr_mip->w1->w[0],mr_mip->w1->w[0]=sr; break; } a=1; b=0; c=0; d=1; m=mr_mip->w1->w[n-1]+1; if (mr_mip->base==0) { #ifndef MR_NOFULLWIDTH if (m==0) { u=mr_mip->w1->w[n-1]; v=mr_mip->w2->w[n-1]; } else { u=muldvm(mr_mip->w1->w[n-1],mr_mip->w1->w[n-2],m,&sr); v=muldvm(mr_mip->w2->w[n-1],mr_mip->w2->w[n-2],m,&sr); } #endif } else { u=muldiv(mr_mip->w1->w[n-1],mr_mip->base,mr_mip->w1->w[n-2],m,&sr); v=muldiv(mr_mip->w2->w[n-1],mr_mip->base,mr_mip->w2->w[n-2],m,&sr); } forever { /* work only with most significant piece */ if (((v+c)==0) || ((v+d)==0)) break; lq=MR_DIV((u+a),(v+c)); if (lq!=MR_DIV((u+b),(v+d))) break; if (lq>=(mr_small)(MR_TOOBIG/mr_abs(d))) break; q=(int)lq; r=a-q*c; a=c; c=r; r=b-q*d; b=d; d=r; lr=u-lq*v; u=v; v=lr; } } copy(mr_mip->w1,z); MR_OUT return (size(mr_mip->w1)); }