// PureNoise CryptoLib (c) 1997-2004, PureNoise Ltd Vaduz <www.cryptolib.com>

// Ruptor's C and Intel Assembly implementations of multiplicative inverse modulo 2^32

/* A pure C version *\

unsigned long inv32 (const unsigned long x)
{
	unsigned long d = x - 1, c = (x >> 1) + 1, a = 0, i = 1;
	
	for (; i; i <<= 1) if (d & 1) d >>= 1, d += c, a |= i; else d >>= 1;
	return a + 1;
}
*/

/* Intel/AMD version */

static __forceinline unsigned long inv32 (const unsigned long X)
{
	_asm
	{
			mov		ecx,X
			mov		edx,X
			shr		ecx,1
			dec		edx
			inc		ecx
			shr		edx,1
			jnc		__00
			lea		edx,[edx+ecx]
__00:		rcr		eax,1
			shr		edx,1
			jnc		__01
			lea		edx,[edx+ecx]
__01:		rcr		eax,1
			shr		edx,1
			jnc		__02
			lea		edx,[edx+ecx]
__02:		rcr		eax,1
			shr		edx,1
			jnc		__03
			lea		edx,[edx+ecx]
__03:		rcr		eax,1
			shr		edx,1
			jnc		__04
			lea		edx,[edx+ecx]
__04:		rcr		eax,1
			shr		edx,1
			jnc		__05
			lea		edx,[edx+ecx]
__05:		rcr		eax,1
			shr		edx,1
			jnc		__06
			lea		edx,[edx+ecx]
__06:		rcr		eax,1
			shr		edx,1
			jnc		__07
			lea		edx,[edx+ecx]
__07:		rcr		eax,1
			shr		edx,1
			jnc		__08
			lea		edx,[edx+ecx]
__08:		rcr		eax,1
			shr		edx,1
			jnc		__09
			lea		edx,[edx+ecx]
__09:		rcr		eax,1
			shr		edx,1
			jnc		__0a
			lea		edx,[edx+ecx]
__0a:		rcr		eax,1
			shr		edx,1
			jnc		__0b
			lea		edx,[edx+ecx]
__0b:		rcr		eax,1
			shr		edx,1
			jnc		__0c
			lea		edx,[edx+ecx]
__0c:		rcr		eax,1
			shr		edx,1
			jnc		__0d
			lea		edx,[edx+ecx]
__0d:		rcr		eax,1
			shr		edx,1
			jnc		__0e
			lea		edx,[edx+ecx]
__0e:		rcr		eax,1
			shr		edx,1
			jnc		__0f
			lea		edx,[edx+ecx]
__0f:		rcr		eax,1
			shr		edx,1
			jnc		__10
			lea		edx,[edx+ecx]
__10:		rcr		eax,1
			shr		edx,1
			jnc		__11
			lea		edx,[edx+ecx]
__11:		rcr		eax,1
			shr		edx,1
			jnc		__12
			lea		edx,[edx+ecx]
__12:		rcr		eax,1
			shr		edx,1
			jnc		__13
			lea		edx,[edx+ecx]
__13:		rcr		eax,1
			shr		edx,1
			jnc		__14
			lea		edx,[edx+ecx]
__14:		rcr		eax,1
			shr		edx,1
			jnc		__15
			lea		edx,[edx+ecx]
__15:		rcr		eax,1
			shr		edx,1
			jnc		__16
			lea		edx,[edx+ecx]
__16:		rcr		eax,1
			shr		edx,1
			jnc		__17
			lea		edx,[edx+ecx]
__17:		rcr		eax,1
			shr		edx,1
			jnc		__18
			lea		edx,[edx+ecx]
__18:		rcr		eax,1
			shr		edx,1
			jnc		__19
			lea		edx,[edx+ecx]
__19:		rcr		eax,1
			shr		edx,1
			jnc		__1a
			lea		edx,[edx+ecx]
__1a:		rcr		eax,1
			shr		edx,1
			jnc		__1b
			lea		edx,[edx+ecx]
__1b:		rcr		eax,1
			shr		edx,1
			jnc		__1c
			lea		edx,[edx+ecx]
__1c:		rcr		eax,1
			shr		edx,1
			jnc		__1d
			lea		edx,[edx+ecx]
__1d:		rcr		eax,1
			shr		edx,1
			jnc		__1e
			lea		edx,[edx+ecx]
__1e:		rcr		eax,1
			shr		edx,1
			jnc		__1f
			lea		edx,[edx+ecx]
__1f:		rcr		eax,1
			inc		eax
	}
}

/* A faster Pentium-only version. Doesn't run on some AMD processors. *\

static __forceinline unsigned long inv32 (const unsigned long X)
{
	_asm
	{
			xor		edi,edi
			mov		esi,X
			mov		edx,X
			shr		esi,1
			dec		edx
			inc		esi
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			add		edx,ecx
			shr		edx,1
			mov		ecx,edi
			cmovc	ecx,esi
			rcr		eax,1
			inc		eax
	}
}
*/
