#include "bn_lcl.h"
/* The old slow way */
-#if 0
-int BN_div(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx)
+#if 1
+int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
+ BN_CTX *ctx)
{
int i,nm,nd;
+ int ret = 0;
BIGNUM *D;
bn_check_top(m);
return(1);
}
- D= &(ctx->bn[ctx->tos]);
- if (dv == NULL) dv= &(ctx->bn[ctx->tos+1]);
- if (rem == NULL) rem= &(ctx->bn[ctx->tos+2]);
+ BN_CTX_start(ctx);
+ D = BN_CTX_get(ctx);
+ if (dv == NULL) dv = BN_CTX_get(ctx);
+ if (rem == NULL) rem = BN_CTX_get(ctx);
+ if (D == NULL || dv == NULL || rem == NULL)
+ goto end;
nd=BN_num_bits(d);
nm=BN_num_bits(m);
- if (BN_copy(D,d) == NULL) return(0);
- if (BN_copy(rem,m) == NULL) return(0);
+ if (BN_copy(D,d) == NULL) goto end;
+ if (BN_copy(rem,m) == NULL) goto end;
/* The next 2 are needed so we can do a dv->d[0]|=1 later
* since BN_lshift1 will only work once there is a value :-) */
bn_wexpand(dv,1);
dv->top=1;
- if (!BN_lshift(D,D,nm-nd)) return(0);
+ if (!BN_lshift(D,D,nm-nd)) goto end;
for (i=nm-nd; i>=0; i--)
{
- if (!BN_lshift1(dv,dv)) return(0);
+ if (!BN_lshift1(dv,dv)) goto end;
if (BN_ucmp(rem,D) >= 0)
{
dv->d[0]|=1;
- if (!BN_usub(rem,rem,D)) return(0);
+ if (!BN_usub(rem,rem,D)) goto end;
}
/* CAN IMPROVE (and have now :=) */
- if (!BN_rshift1(D,D)) return(0);
+ if (!BN_rshift1(D,D)) goto end;
}
rem->neg=BN_is_zero(rem)?0:m->neg;
dv->neg=m->neg^d->neg;
- return(1);
+ ret = 1;
+ end:
+ BN_CTX_end(ctx);
+ return(ret);
}
#else
return(1);
}
- tmp= &(ctx->bn[ctx->tos]);
+ BN_CTX_start(ctx);
+ tmp=BN_CTX_get(ctx);
tmp->neg=0;
- snum= &(ctx->bn[ctx->tos+1]);
- sdiv= &(ctx->bn[ctx->tos+2]);
+ snum=BN_CTX_get(ctx);
+ sdiv=BN_CTX_get(ctx);
if (dv == NULL)
- res= &(ctx->bn[ctx->tos+3]);
+ res=BN_CTX_get(ctx);
else res=dv;
+ if (res == NULL) goto err;
/* First we normalise the numbers */
norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2);
n0=wnump[0];
n1=wnump[-1];
if (n0 == d0)
+ {
q=BN_MASK2;
- else
+#ifdef REMAINDER_IS_ALREADY_CALCULATED /* in this case it isn't */
+ rem=(n1-q*d0)&BN_MASK2;
+#endif
+ }
+ else /* n0 < d0 */
#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0);
#else
*/
rem=(n1-q*d0)&BN_MASK2;
#endif
+#ifdef BN_UMULT_HIGH
+ t2l = d1 * q;
+ t2h = BN_UMULT_HIGH(d1,q);
+#else
t2l=LBITS(d1); t2h=HBITS(d1);
ql =LBITS(q); qh =HBITS(q);
mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */
+#endif
for (;;)
{
BN_rshift(rm,snum,norm_shift);
rm->neg=num->neg;
}
+ BN_CTX_end(ctx);
return(1);
err:
+ BN_CX_end(ctx);
return(0);
}
if (BN_ucmp(m,d) < 0)
return((BN_copy(rem,m) == NULL)?0:1);
- dv= &(ctx->bn[ctx->tos]);
+ BN_CTX_start(ctx);
+ dv=BN_CTX_get(ctx);
- if (!BN_copy(rem,m)) return(0);
+ if (!BN_copy(rem,m)) goto err;
nm=BN_num_bits(rem);
nd=BN_num_bits(d);
- if (!BN_lshift(dv,d,nm-nd)) return(0);
+ if (!BN_lshift(dv,d,nm-nd)) goto err;
for (i=nm-nd; i>=0; i--)
{
if (BN_cmp(rem,dv) >= 0)
{
- if (!BN_sub(rem,rem,dv)) return(0);
+ if (!BN_sub(rem,rem,dv)) goto err;
}
- if (!BN_rshift1(dv,dv)) return(0);
+ if (!BN_rshift1(dv,dv)) goto err;
}
+ BN_CTX_end(ctx);
return(1);
+ err:
+ BN_CTX_end(ctx);
+ return(0);
#else
return(BN_div(NULL,rem,m,d,ctx));
#endif