Beispiel #1
0
static void mr_comba_halfm(big x,big y,big z) 
{
    mr_small extra;
    mr_large dig,carry;

    carry=(mr_large)x[0]*y[0];
    z[0]=(mr_small)carry;
    carry=MR_TOP(carry);

    extra=0;
    carry=(mr_large)x[1]*y[0]+carry;
    dig=(mr_large)x[0]*y[1];
    carry+=dig;
    if (carry<dig) extra=1;
    z[1]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    extra=0;
    carry+=(mr_large)x[2]*y[0];
    dig=(mr_large)x[1]*y[1];
    carry+=dig;
    if (carry<dig) extra=1;
    dig=(mr_large)x[0]*y[2];
    carry+=dig;
    if (carry<dig) extra++;
    z[2]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    extra=0;
    dig=(mr_large)x[3]*y[0];
    carry+=dig;
    dig=(mr_large)x[2]*y[1];
    carry+=dig;
    dig=(mr_large)x[1]*y[2];
    carry+=dig;
    dig=(mr_large)x[0]*y[3];
    carry+=dig;
    z[3]=(mr_small)carry;
    return;
}
Beispiel #2
0
static int mr_decn(big y,big z,int n)
{ /* subtract from an array of length n*4 */
    int m;
    mr_small borrow=0;
    mr_large u;
    for (m=0;m<4*n;m+=4)
    {
        u=(mr_large)z[m]-y[m]-borrow;
        z[m]=(mr_small)u;
        borrow=0-MR_TOP(u);
        u=(mr_large)z[m+1]-y[m+1]-borrow;
        z[m+1]=(mr_small)u;
        borrow=0-MR_TOP(u);
        u=(mr_large)z[m+2]-y[m+2]-borrow;
        z[m+2]=(mr_small)u;
        borrow=0-MR_TOP(u);
        u=(mr_large)z[m+3]-y[m+3]-borrow;
        z[m+3]=(mr_small)u;
        borrow=0-MR_TOP(u);
    } 
    return borrow; 
}
Beispiel #3
0
static int mr_incn(big y,big z,int n)
{ /* add to an array of length n*4 */
    int m;
    mr_small carry=0;
    mr_large u;
    for (m=0;m<4*n;m+=4)
    {
        u=(mr_large)carry+z[m]+y[m];
        z[m]=(mr_small)u;
        carry=MR_TOP(u); 
        u=(mr_large)carry+z[m+1]+y[m+1];
        z[m+1]=(mr_small)u;
        carry=MR_TOP(u); 
        u=(mr_large)carry+z[m+2]+y[m+2];
        z[m+2]=(mr_small)u;
        carry=MR_TOP(u); 
        u=(mr_large)carry+z[m+3]+y[m+3];
        z[m+3]=(mr_small)u;
        carry=MR_TOP(u); 
    }
    return carry;
}
Beispiel #4
0
static int mr_addn(big x,big y,big z,int n)
{ /* add two arrays of length n*4 */
    int m;
    mr_small carry=0;
    mr_large u;

    for (m=0;m<4*n;m+=4)
    { /* unroll the loops 4 times and hope to God for a decent compiler.... */
        u=(mr_large)carry+x[m]+y[m];
        z[m]=(mr_small)u;
        carry=MR_TOP(u);
        u=(mr_large)carry+x[m+1]+y[m+1];
        z[m+1]=(mr_small)u;
        carry=MR_TOP(u);
        u=(mr_large)carry+x[m+2]+y[m+2];
        z[m+2]=(mr_small)u;
        carry=MR_TOP(u);
        u=(mr_large)carry+x[m+3]+y[m+3];
        z[m+3]=(mr_small)u;
        carry=MR_TOP(u);
    } 
    return carry;
}
Beispiel #5
0
static void mr_comba_sqr(big x,big z)
{ /* square an array of length MR_KCM */
    mr_small extra;
    mr_large dig,carry;

/* going up the pyramid of partial products.... */

    carry=(mr_large)x[0]*x[0];
    z[0]=(mr_small)carry;
    carry=MR_TOP(carry);

    extra=0;
    dig=(mr_large)x[0]*x[1];
    carry+=dig;
    carry+=dig;
    if (carry<dig) extra=1;
    z[1]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    extra=0;
    dig=(mr_large)x[2]*x[0];
    carry+=dig;
    carry+=dig;
    if (carry<dig) extra=1;
    dig=(mr_large)x[1]*x[1];
    carry+=dig;
    if (carry<dig) extra++;
    z[2]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    extra=0;
    dig=(mr_large)x[3]*x[0];
    carry+=dig;
    if (carry<dig) extra=1;
    carry+=dig;
    if (carry<dig) extra++;
    dig=(mr_large)x[2]*x[1];
    carry+=dig;
    if (carry<dig) extra++;
    carry+=dig;
    if (carry<dig) extra++;
    z[3]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    extra=0;
    dig=(mr_large)x[3]*x[1];
    carry+=dig;
    if (carry<dig) extra=1;
    carry+=dig;
    if (carry<dig) extra++;
    dig=(mr_large)x[2]*x[2];
    carry+=dig;
    if (carry<dig) extra++;
    z[4]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    extra=0;
    dig=(mr_large)x[3]*x[2];
    carry+=dig;
    if (carry<dig) extra=1;
    carry+=dig;
    if (carry<dig) extra++;
    z[5]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    dig=(mr_large)x[3]*x[3];
    carry+=dig;
    z[6]=(mr_small)carry;
    z[7]=MR_TOP(carry);

    return;
}
Beispiel #6
0
static void mr_comba_mul(big x,big y,big z)
{ /* unwound Comba code for 4x4 multiply */
    mr_small extra;
    mr_large dig,carry;

/* going up the pyramid of partial products.... */

    carry=(mr_large)x[0]*y[0];
    z[0]=(mr_small)carry;
    carry=MR_TOP(carry);

    extra=0;
    carry+=(mr_large)x[1]*y[0];
    dig=(mr_large)x[0]*y[1];
    carry+=dig;
    if (carry<dig) extra=1;
    z[1]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    extra=0;
    carry+=(mr_large)x[2]*y[0];  /* never overflows! */
    dig=(mr_large)x[1]*y[1];
    carry+=dig;
    if (carry<dig) extra=1;
    dig=(mr_large)x[0]*y[2];
    carry+=dig;
    if (carry<dig) extra++;
    z[2]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     
    
    extra=0;
    dig=(mr_large)x[3]*y[0];
    carry+=dig;
    if (carry<dig) extra=1;
    dig=(mr_large)x[2]*y[1];
    carry+=dig;
    if (carry<dig) extra++;
    dig=(mr_large)x[1]*y[2];
    carry+=dig;
    if (carry<dig) extra++;
    dig=(mr_large)x[0]*y[3];
    carry+=dig;
    if (carry<dig) extra++;
    z[3]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    extra=0;
    dig=(mr_large)x[3]*y[1];
    carry+=dig;
    if (carry<dig) extra=1;
    dig=(mr_large)x[2]*y[2];
    carry+=dig;
    if (carry<dig) extra++;
    dig=(mr_large)x[1]*y[3];
    carry+=dig;
    if (carry<dig) extra++;
    z[4]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    extra=0;
    dig=(mr_large)x[3]*y[2];
    carry+=dig;
    if (carry<dig) extra=1;
    dig=(mr_large)x[2]*y[3];
    carry+=dig;
    if (carry<dig) extra++;
    z[5]=(mr_small)carry;
    carry=MR_TOP(carry);
    MR_TOP(carry)=extra;     

    dig=(mr_large)x[3]*y[3];
    carry+=dig;
    z[6]=(mr_small)carry;
    z[7]=MR_TOP(carry);

    return;
}
Beispiel #7
0
int xgcd(_MIPD_ big x,big y,big xd,big yd,big z)
{   /* greatest common divisor by Euclids method  *
     * extended to also calculate xd and yd where *
     *      z = x.xd + y.yd = gcd(x,y)            *
     * if xd, yd not distinct, only xd calculated *
     * z only returned if distinct from xd and yd *
     * xd will always be positive, yd negative    */

    int s,n,iter;
    mr_small r,a,b,c,d;
    mr_small q,m,sr;
#ifdef MR_FP
    mr_small dres;
#endif

#ifdef mr_dltype
    mr_large u,v,lr;
#else
    mr_small u,v,lr;
#endif

    BOOL last,dplus=TRUE;
    big t;
#ifndef MR_GENERIC_MT
    miracl *mr_mip=get_mip();
#endif
    if (mr_mip->ERNUM) return 0;

    MR_IN(30)

    copy(x,mr_mip->w1);
    copy(y,mr_mip->w2);
    s=exsign(mr_mip->w1);
    insign(PLUS,mr_mip->w1);
    insign(PLUS,mr_mip->w2);
    convert(_MIPP_ 1,mr_mip->w3);
    zero(mr_mip->w4);
    last=FALSE;
    a=b=c=d=0;
    iter=0;

    while (size(mr_mip->w2)!=0)
    {
        if (b==0)
        {   /* update mr_mip->w1 and mr_mip->w2 */
            divide(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w5);
            t=mr_mip->w1,mr_mip->w1=mr_mip->w2,mr_mip->w2=t;    /* swap(mr_mip->w1,mr_mip->w2) */
            multiply(_MIPP_ mr_mip->w4,mr_mip->w5,mr_mip->w0);
            add(_MIPP_ mr_mip->w3,mr_mip->w0,mr_mip->w3);
            t=mr_mip->w3,mr_mip->w3=mr_mip->w4,mr_mip->w4=t;    /* swap(xd,yd) */
            iter++;
        }
        else
        {

            /*  printf("a= %d b= %d c= %d  d= %d \n",a,b,c,d);   */

            mr_pmul(_MIPP_ mr_mip->w1,c,mr_mip->w5);   /* c*w1 */
            mr_pmul(_MIPP_ mr_mip->w1,a,mr_mip->w1);   /* a*w1 */
            mr_pmul(_MIPP_ mr_mip->w2,b,mr_mip->w0);   /* b*w2 */
            mr_pmul(_MIPP_ mr_mip->w2,d,mr_mip->w2);   /* d*w2 */


            if (!dplus)
            {
                mr_psub(_MIPP_ mr_mip->w0,mr_mip->w1,mr_mip->w1); /* b*w2-a*w1 */
                mr_psub(_MIPP_ mr_mip->w5,mr_mip->w2,mr_mip->w2); /* c*w1-d*w2 */
            }
            else
            {
                mr_psub(_MIPP_ mr_mip->w1,mr_mip->w0,mr_mip->w1); /* a*w1-b*w2 */
                mr_psub(_MIPP_ mr_mip->w2,mr_mip->w5,mr_mip->w2); /* d*w2-c*w1 */
            }
            mr_pmul(_MIPP_ mr_mip->w3,c,mr_mip->w5);
            mr_pmul(_MIPP_ mr_mip->w3,a,mr_mip->w3);
            mr_pmul(_MIPP_ mr_mip->w4,b,mr_mip->w0);
            mr_pmul(_MIPP_ mr_mip->w4,d,mr_mip->w4);

            if (a==0) copy(mr_mip->w0,mr_mip->w3);
            else      mr_padd(_MIPP_ mr_mip->w3,mr_mip->w0,mr_mip->w3);
            mr_padd(_MIPP_ mr_mip->w4,mr_mip->w5,mr_mip->w4);
        }
        if (mr_mip->ERNUM || size(mr_mip->w2)==0) break;


        n=(int)mr_mip->w1->len;
        if (n==1)
        {
            last=TRUE;
            u=mr_mip->w1->w[0];
            v=mr_mip->w2->w[0];
        }
        else
        {
            m=mr_mip->w1->w[n-1]+1;
            if (mr_mip->base==0)
            {
#ifndef MR_NOFULLWIDTH
#ifdef mr_dltype
                /* use double length type if available */
                if (n>2 && m!=0)
                {   /* squeeze out as much significance as possible */
                    MR_TOP(u)=muldvm(mr_mip->w1->w[n-1],mr_mip->w1->w[n-2],m,&sr);
                    MR_BOT(u)=muldvm(sr,mr_mip->w1->w[n-3],m,&sr);
                    MR_TOP(v)=muldvm(mr_mip->w2->w[n-1],mr_mip->w2->w[n-2],m,&sr);
                    MR_BOT(v)=muldvm(sr,mr_mip->w2->w[n-3],m,&sr);
                }
                else
                {
                    MR_TOP(u)=mr_mip->w1->w[n-1];
                    MR_BOT(u)=mr_mip->w1->w[n-2];
                    MR_TOP(v)=mr_mip->w2->w[n-1];
                    MR_BOT(v)=mr_mip->w2->w[n-2];
                    if (n==2) last=TRUE;
                }
#else
                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
#endif
            }
            else
            {
#ifdef mr_dltype
                if (n>2)
                {   /* squeeze out as much significance as possible */
                    u=muldiv(mr_mip->w1->w[n-1],mr_mip->base,mr_mip->w1->w[n-2],m,&sr);
                    u=u*mr_mip->base+muldiv(sr,mr_mip->base,mr_mip->w1->w[n-3],m,&sr);
                    v=muldiv(mr_mip->w2->w[n-1],mr_mip->base,mr_mip->w2->w[n-2],m,&sr);
                    v=v*mr_mip->base+muldiv(sr,mr_mip->base,mr_mip->w2->w[n-3],m,&sr);
                }
                else
                {
                    u=(mr_large)mr_mip->base*mr_mip->w1->w[n-1]+mr_mip->w1->w[n-2];
                    v=(mr_large)mr_mip->base*mr_mip->w2->w[n-1]+mr_mip->w2->w[n-2];
                    last=TRUE;
                }
#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);
#endif
            }
        }

        dplus=TRUE;
        a=1;
        b=0;
        c=0;
        d=1;

        forever
        {   /* work only with most significant piece */
            if (last)
            {
                if (v==0) break;
                q=qdiv(u,v);
                if (q==0) break;
            }
            else
            {
                if (dplus)
                {
                    if (v-c==0 || v+d==0) break;
                    q=qdiv(u+a,v-c);
                    if (q==0) break;
                    if (q!=qdiv(u-b,v+d)) break;
                }
                else
                {
                    if (v+c==0 || v-d==0) break;
                    q=qdiv(u-a,v+c);
                    if (q==0) break;
                    if (q!=qdiv(u+b,v-d)) break;
                }
            }

            if (q==1)
            {
                if (b+d >= MAXBASE) break;
                r=a+c;
                a=c;
                c=r;
                r=b+d;
                b=d;
                d=r;
                lr=u-v;
                u=v;
                v=lr;
            }
            else
            {
                if (q>=MR_DIV(MAXBASE-b,d)) break;
                r=a+q*c;
                a=c;
                c=r;
                r=b+q*d;
                b=d;
                d=r;
                lr=u-q*v;
                u=v;
                v=lr;
            }
            iter++;
            dplus=!dplus;
        }
        iter%=2;
    }

    if (s==MINUS) iter++;
    if (iter%2==1) subtract(_MIPP_ y,mr_mip->w3,mr_mip->w3);

    if (xd!=yd)
    {
        negify(x,mr_mip->w2);
        mad(_MIPP_ mr_mip->w2,mr_mip->w3,mr_mip->w1,y,mr_mip->w4,mr_mip->w4);
        copy(mr_mip->w4,yd);
    }
    copy(mr_mip->w3,xd);
    if (z!=xd && z!=yd) copy(mr_mip->w1,z);

    MR_OUT
    return (size(mr_mip->w1));
}
Beispiel #8
0
int xgcd(_MIPD_ big x,big y,big xd,big yd,big z)
{ /* greatest common divisor by Euclids method  *
   * extended to also calculate xd and yd where *
   *      z = x.xd + y.yd = gcd(x,y)            *
   * if xd, yd not distinct, only xd calculated *
   * z only returned if distinct from xd and yd *
   * xd will always be positive, yd negative    */
    int q,r,a,b,c,d,s,n;
    mr_small m,sr;
#ifdef mr_dltype
    mr_large u,v,lq,lr;
#else
    mr_small u,v,lq,lr;
#endif

    BOOL last;
    big t;
#ifndef MR_GENERIC_MT
    miracl *mr_mip=get_mip();
#endif
    if (mr_mip->ERNUM) return 0;

    MR_IN(30)

    copy(x,mr_mip->w1);
    copy(y,mr_mip->w2);
    s=exsign(mr_mip->w1);
    insign(PLUS,mr_mip->w1);
    insign(PLUS,mr_mip->w2);
/*    copy(mr_mip->w1,mr_mip->w3);
    copy(mr_mip->w2,mr_mip->w4);  */
    convert(_MIPP_ 1,mr_mip->w3);
    zero(mr_mip->w4);
    last=FALSE;
    a=b=c=d=0;
    while (size(mr_mip->w2)!=0)
    {
        if (b==0)
        { /* update mr_mip->w1 and mr_mip->w2 */
            divide(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w5);
            t=mr_mip->w1,mr_mip->w1=mr_mip->w2,mr_mip->w2=t;    /* swap(mr_mip->w1,mr_mip->w2) */
            multiply(_MIPP_ mr_mip->w4,mr_mip->w5,mr_mip->w0);
            subtract(_MIPP_ mr_mip->w3,mr_mip->w0,mr_mip->w3);
            t=mr_mip->w3,mr_mip->w3=mr_mip->w4,mr_mip->w4=t;    /* swap(xd,yd) */
        }
        else
        {
            premult(_MIPP_ mr_mip->w1,c,mr_mip->w5);
            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_r(_MIPP_ mr_mip->w1,mr_mip->w0,mr_mip->w1);
            add_r(_MIPP_ mr_mip->w2,mr_mip->w5,mr_mip->w2);
            premult(_MIPP_ mr_mip->w3,c,mr_mip->w5);
            premult(_MIPP_ mr_mip->w3,a,mr_mip->w3);
            premult(_MIPP_ mr_mip->w4,b,mr_mip->w0);
            premult(_MIPP_ mr_mip->w4,d,mr_mip->w4);
            add_r(_MIPP_ mr_mip->w3,mr_mip->w0,mr_mip->w3);
            add_r(_MIPP_ mr_mip->w4,mr_mip->w5,mr_mip->w4);
        }
        if (mr_mip->ERNUM || size(mr_mip->w2)==0) break;
        n=(int)mr_mip->w1[0];
        a=1;
        b=0;
        c=0;
        d=1;
        if (n==1)
        {
            last=TRUE;
            u=mr_mip->w1[1];
            v=mr_mip->w2[1];
        }
        else
        {
            m=mr_mip->w1[n]+1;
            if (mr_mip->base==0)
            {
#ifdef mr_dltype
 /* use double length type if available */
                if (n>2 && m!=0)
                { /* squeeze out as much significance as possible */
                    MR_TOP(u)=muldvm(mr_mip->w1[n],mr_mip->w1[n-1],m,&sr);
                    MR_BOT(u)=muldvm(sr,mr_mip->w1[n-2],m,&sr);
                    MR_TOP(v)=muldvm(mr_mip->w2[n],mr_mip->w2[n-1],m,&sr);
                    MR_BOT(v)=muldvm(sr,mr_mip->w2[n-2],m,&sr);
                }
                else
                {
                    MR_TOP(u)=mr_mip->w1[n];
                    MR_BOT(u)=mr_mip->w1[n-1];
                    MR_TOP(v)=mr_mip->w2[n];
                    MR_BOT(v)=mr_mip->w2[n-1];
                    if (n==2) last=TRUE;
                }
#else
                if (m==0)
                {
                    u=mr_mip->w1[n];
                    v=mr_mip->w2[n];
                }
                else
                {
                    u=muldvm(mr_mip->w1[n],mr_mip->w1[n-1],m,&sr);
                    v=muldvm(mr_mip->w2[n],mr_mip->w2[n-1],m,&sr);
                }
#endif
            }
            else
            {
#ifdef mr_dltype
 /* use double length type if available */
                if (n>2)
                { /* squeeze out as much significance as possible */
                    u=muldiv(mr_mip->w1[n],mr_mip->base,mr_mip->w1[n-1],m,&sr);
                    u=u*mr_mip->base+muldiv(sr,mr_mip->base,mr_mip->w1[n-2],m,&sr);
                    v=muldiv(mr_mip->w2[n],mr_mip->base,mr_mip->w2[n-1],m,&sr);
                    v=v*mr_mip->base+muldiv(sr,mr_mip->base,mr_mip->w2[n-2],m,&sr);
                }
                else
                {
                    u=(mr_large)mr_mip->base*mr_mip->w1[n]+mr_mip->w1[n-1];
                    v=(mr_large)mr_mip->base*mr_mip->w2[n]+mr_mip->w2[n-1];
                    last=TRUE;
                }
#else
                u=muldiv(mr_mip->w1[n],mr_mip->base,mr_mip->w1[n-1],m,&sr);
                v=muldiv(mr_mip->w2[n],mr_mip->base,mr_mip->w2[n-1],m,&sr);
#endif
            }
        }
        forever
        { /* work only with most significant piece */
            if (last)
            {
                if (v==0) break;
                lq=u/v;
            }
            else
            {
                if (((v+c)==0) || ((v+d)==0)) break;
                lq=(u+a)/(v+c);
                if (lq!=(u+b)/(v+d)) break;
            }
#ifdef mr_dltype
            if (lq>=(mr_large)(MR_TOOBIG/abs(d))) break;
#else
            if (lq>=(mr_small)(MR_TOOBIG/abs(d))) break;
#endif
            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;
        }
    }
    if (s==MINUS) negate(mr_mip->w3,mr_mip->w3);
    if (size(mr_mip->w3)<=0) add_r(_MIPP_ mr_mip->w3,y,mr_mip->w3);
    if (xd!=yd)
    {
        negate(x,mr_mip->w2);
        mad(_MIPP_ mr_mip->w2,mr_mip->w3,mr_mip->w1,y,mr_mip->w4,mr_mip->w4);
        copy(mr_mip->w4,yd);
    }
    copy(mr_mip->w3,xd);
    if (z!=xd && z!=yd) copy(mr_mip->w1,z);
    MR_OUT
    return (size(mr_mip->w1));
}