int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BN_RECP_CTX *recp,
	     BN_CTX *ctx)
	{
	int i,j,ret=0,ex;
	BIGNUM *a,*b,*d,*r;

	BN_CTX_start(ctx);
	a=BN_CTX_get(ctx);
	b=BN_CTX_get(ctx);
	if (dv != NULL)
		d=dv;
	else
		d=BN_CTX_get(ctx);
	if (rem != NULL)
		r=rem;
	else
		r=BN_CTX_get(ctx);
	if (a == NULL || b == NULL || d == NULL || r == NULL) goto err;

	if (BN_ucmp(m,&(recp->N)) < 0)
		{
		BN_zero(d);
		BN_copy(r,m);
		BN_CTX_end(ctx);
		return(1);
		}

	/* We want the remainder
	 * Given input of ABCDEF / ab
	 * we need multiply ABCDEF by 3 digests of the reciprocal of ab
	 *
	 */
	i=BN_num_bits(m);
	if (i%2) i--;

	j=recp->num_bits*2;
	if (j > i)
		{
		i=j;
		ex=0;
		}
	else
		{
		ex=(i-j)/2;
		}

	j=i/2;

	if (i != recp->shift)
		recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N),
			i,ctx);

	if (!BN_rshift(a,m,j-ex)) goto err;
	if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err;
	if (!BN_rshift(d,b,j+ex)) goto err;
	d->neg=0;
	if (!BN_mul(b,&(recp->N),d,ctx)) goto err;
	if (!BN_usub(r,m,b)) goto err;
	r->neg=0;

	j=0;
#if 1
	while (BN_ucmp(r,&(recp->N)) >= 0)
		{
		if (j++ > 2)
			{
#if 1
			/* work around some bug:
			   -1CC0E177F93042B29D309839F8019DB93404D7A395F1E162
			   5383BF622A20B17E1BAA999336988B82B93F5FB77B55B4B68
			   9412000000000031 / 298EB5957DBFB8CBB2CC2A9F789D2B5
			   fails, for example. */
			ret=BN_div(dv,rem,m,&(recp->N),ctx);
#else
			BNerr(BN_F_BN_MOD_MUL_RECIPROCAL,BN_R_BAD_RECIPROCAL);
#endif
			goto err;
			}
		if (!BN_usub(r,r,&(recp->N))) goto err;
		if (!BN_add_word(d,1)) goto err;
		}
#endif

	r->neg=BN_is_zero(r)?0:m->neg;
	d->neg=m->neg^recp->N.neg;
	ret=1;
err:
	BN_CTX_end(ctx);
	return(ret);
	}