int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
	{
	BIGNUM *b, *c, *u, *v, *tmp;
	int ret = 0;
	bn_check_top(a);
	bn_check_top(p);
	BN_CTX_start(ctx);
	if ((b = BN_CTX_get(ctx))==NULL) goto err;
	if ((c = BN_CTX_get(ctx))==NULL) goto err;
	if ((u = BN_CTX_get(ctx))==NULL) goto err;
	if ((v = BN_CTX_get(ctx))==NULL) goto err;
	if (!BN_GF2m_mod(u, a, p)) goto err;
	if (BN_is_zero(u)) goto err;
	if (!BN_copy(v, p)) goto err;
#if 0
	if (!BN_one(b)) goto err;
	while (1)
		{
		while (!BN_is_odd(u))
			{
			if (!BN_rshift1(u, u)) goto err;
			if (BN_is_odd(b))
				{
				if (!BN_GF2m_add(b, b, p)) goto err;
				}
			if (!BN_rshift1(b, b)) goto err;
			}
		if (BN_abs_is_word(u, 1)) break;
		if (BN_num_bits(u) < BN_num_bits(v))
			{
			tmp = u; u = v; v = tmp;
			tmp = b; b = c; c = tmp;
			}
		if (!BN_GF2m_add(u, u, v)) goto err;
		if (!BN_GF2m_add(b, b, c)) goto err;
		}
#else
	{
	int i,	ubits = BN_num_bits(u),
		vbits = BN_num_bits(v),
		top = p->top;
	BN_ULONG *udp,*bdp,*vdp,*cdp;
	bn_wexpand(u,top);	udp = u->d;
				for (i=u->top;i<top;i++) udp[i] = 0;
				u->top = top;
	bn_wexpand(b,top);	bdp = b->d;
				bdp[0] = 1;
				for (i=1;i<top;i++) bdp[i] = 0;
				b->top = top;
	bn_wexpand(c,top);	cdp = c->d;
				for (i=0;i<top;i++) cdp[i] = 0;
				c->top = top;
	vdp = v->d;
	while (1)
		{
		while (ubits && !(udp[0]&1))
			{
			BN_ULONG u0,u1,b0,b1,mask;
			u0   = udp[0];
			b0   = bdp[0];
			mask = (BN_ULONG)0-(b0&1);
			b0  ^= p->d[0]&mask;
			for (i=0;i<top-1;i++)
				{
				u1 = udp[i+1];
				udp[i] = ((u0>>1)|(u1<<(BN_BITS2-1)))&BN_MASK2;
				u0 = u1;
				b1 = bdp[i+1]^(p->d[i+1]&mask);
				bdp[i] = ((b0>>1)|(b1<<(BN_BITS2-1)))&BN_MASK2;
				b0 = b1;
				}
			udp[i] = u0>>1;
			bdp[i] = b0>>1;
			ubits--;
			}
		if (ubits<=BN_BITS2 && udp[0]==1) break;
		if (ubits<vbits)
			{
			i = ubits; ubits = vbits; vbits = i;
			tmp = u; u = v; v = tmp;
			tmp = b; b = c; c = tmp;
			udp = vdp; vdp = v->d;
			bdp = cdp; cdp = c->d;
			}
		for(i=0;i<top;i++)
			{
			udp[i] ^= vdp[i];
			bdp[i] ^= cdp[i];
			}
		if (ubits==vbits)
			{
			bn_fix_top(u);
			ubits = BN_num_bits(u);
			}
		}
	bn_fix_top(b);
	}
#endif
	if (!BN_copy(r, b)) goto err;
	bn_check_top(r);
	ret = 1;
err:
  	BN_CTX_end(ctx);
	return ret;
	}
['int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)\n\t{\n\tBIGNUM *b, *c, *u, *v, *tmp;\n\tint ret = 0;\n\tbn_check_top(a);\n\tbn_check_top(p);\n\tBN_CTX_start(ctx);\n\tif ((b = BN_CTX_get(ctx))==NULL) goto err;\n\tif ((c = BN_CTX_get(ctx))==NULL) goto err;\n\tif ((u = BN_CTX_get(ctx))==NULL) goto err;\n\tif ((v = BN_CTX_get(ctx))==NULL) goto err;\n\tif (!BN_GF2m_mod(u, a, p)) goto err;\n\tif (BN_is_zero(u)) goto err;\n\tif (!BN_copy(v, p)) goto err;\n#if 0\n\tif (!BN_one(b)) goto err;\n\twhile (1)\n\t\t{\n\t\twhile (!BN_is_odd(u))\n\t\t\t{\n\t\t\tif (!BN_rshift1(u, u)) goto err;\n\t\t\tif (BN_is_odd(b))\n\t\t\t\t{\n\t\t\t\tif (!BN_GF2m_add(b, b, p)) goto err;\n\t\t\t\t}\n\t\t\tif (!BN_rshift1(b, b)) goto err;\n\t\t\t}\n\t\tif (BN_abs_is_word(u, 1)) break;\n\t\tif (BN_num_bits(u) < BN_num_bits(v))\n\t\t\t{\n\t\t\ttmp = u; u = v; v = tmp;\n\t\t\ttmp = b; b = c; c = tmp;\n\t\t\t}\n\t\tif (!BN_GF2m_add(u, u, v)) goto err;\n\t\tif (!BN_GF2m_add(b, b, c)) goto err;\n\t\t}\n#else\n\t{\n\tint i,\tubits = BN_num_bits(u),\n\t\tvbits = BN_num_bits(v),\n\t\ttop = p->top;\n\tBN_ULONG *udp,*bdp,*vdp,*cdp;\n\tbn_wexpand(u,top);\tudp = u->d;\n\t\t\t\tfor (i=u->top;i<top;i++) udp[i] = 0;\n\t\t\t\tu->top = top;\n\tbn_wexpand(b,top);\tbdp = b->d;\n\t\t\t\tbdp[0] = 1;\n\t\t\t\tfor (i=1;i<top;i++) bdp[i] = 0;\n\t\t\t\tb->top = top;\n\tbn_wexpand(c,top);\tcdp = c->d;\n\t\t\t\tfor (i=0;i<top;i++) cdp[i] = 0;\n\t\t\t\tc->top = top;\n\tvdp = v->d;\n\twhile (1)\n\t\t{\n\t\twhile (ubits && !(udp[0]&1))\n\t\t\t{\n\t\t\tBN_ULONG u0,u1,b0,b1,mask;\n\t\t\tu0   = udp[0];\n\t\t\tb0   = bdp[0];\n\t\t\tmask = (BN_ULONG)0-(b0&1);\n\t\t\tb0  ^= p->d[0]&mask;\n\t\t\tfor (i=0;i<top-1;i++)\n\t\t\t\t{\n\t\t\t\tu1 = udp[i+1];\n\t\t\t\tudp[i] = ((u0>>1)|(u1<<(BN_BITS2-1)))&BN_MASK2;\n\t\t\t\tu0 = u1;\n\t\t\t\tb1 = bdp[i+1]^(p->d[i+1]&mask);\n\t\t\t\tbdp[i] = ((b0>>1)|(b1<<(BN_BITS2-1)))&BN_MASK2;\n\t\t\t\tb0 = b1;\n\t\t\t\t}\n\t\t\tudp[i] = u0>>1;\n\t\t\tbdp[i] = b0>>1;\n\t\t\tubits--;\n\t\t\t}\n\t\tif (ubits<=BN_BITS2 && udp[0]==1) break;\n\t\tif (ubits<vbits)\n\t\t\t{\n\t\t\ti = ubits; ubits = vbits; vbits = i;\n\t\t\ttmp = u; u = v; v = tmp;\n\t\t\ttmp = b; b = c; c = tmp;\n\t\t\tudp = vdp; vdp = v->d;\n\t\t\tbdp = cdp; cdp = c->d;\n\t\t\t}\n\t\tfor(i=0;i<top;i++)\n\t\t\t{\n\t\t\tudp[i] ^= vdp[i];\n\t\t\tbdp[i] ^= cdp[i];\n\t\t\t}\n\t\tif (ubits==vbits)\n\t\t\t{\n\t\t\tbn_fix_top(u);\n\t\t\tubits = BN_num_bits(u);\n\t\t\t}\n\t\t}\n\tbn_fix_top(b);\n\t}\n#endif\n\tif (!BN_copy(r, b)) goto err;\n\tbn_check_top(r);\n\tret = 1;\nerr:\n  \tBN_CTX_end(ctx);\n\treturn ret;\n\t}']