private BigInteger OddPow( BigInteger b, BigInteger exp ) { BigInteger resultNum = new BigInteger(Montgomery.ToMont(1, mod), mod.length << 1); BigInteger tempNum = new BigInteger(Montgomery.ToMont(b, mod), mod.length << 1); // ensures (tempNum * tempNum) < m^ (2k) uint mPrime = Montgomery.Inverse(mod.data[0]); uint totalBits = ( uint )exp.BitCount(); uint[] wkspace = new uint[mod.length << 1]; // perform squaring and multiply exponentiation for ( uint pos = 0; pos < totalBits; pos++ ) { if ( exp.TestBit(pos) ) { Array.Clear(wkspace, 0, wkspace.Length); Kernel.Multiply(resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0); resultNum.length += tempNum.length; uint[] t = wkspace; wkspace = resultNum.data; resultNum.data = t; Montgomery.Reduce(resultNum, mod, mPrime); } Kernel.SquarePositive(tempNum, ref wkspace); Montgomery.Reduce(tempNum, mod, mPrime); } Montgomery.Reduce(resultNum, mod, mPrime); return resultNum; }
private unsafe BigInteger EvenPow( uint b, BigInteger exp ) { exp.Normalize(); uint[] wkspace = new uint[mod.length << 1 + 1]; BigInteger resultNum = new BigInteger(( BigInteger )b, mod.length << 1 + 1); uint pos = ( uint )exp.BitCount() - 2; // // We know that the first itr will make the val m // do { // // r = r ^ 2 % m // Kernel.SquarePositive(resultNum, ref wkspace); if ( !( resultNum.length < mod.length ) ) BarrettReduction(resultNum); if ( exp.TestBit(pos) ) { // // r = r * m % m // // TODO: Is Unsafe really speeding things up? fixed ( uint* u = resultNum.data ) { uint i = 0; ulong mc = 0; do { mc += ( ulong )u[i] * ( ulong )b; u[i] = ( uint )mc; mc >>= 32; } while ( ++i < resultNum.length ); if ( resultNum.length < mod.length ) { if ( mc != 0 ) { u[i] = ( uint )mc; resultNum.length++; while ( resultNum >= mod ) Kernel.MinusEq(resultNum, mod); } } else if ( mc != 0 ) { // // First, we estimate the quotient by dividing // the first part of each of the numbers. Then // we correct this, if necessary, with a subtraction. // uint cc = ( uint )mc; // We would rather have this estimate overshoot, // so we add one to the divisor uint divEstimate = ( uint )( ( ( ( ulong )cc << 32 ) | ( ulong )u[i - 1] ) / ( mod.data[mod.length - 1] + 1 ) ); uint t; i = 0; mc = 0; do { mc += ( ulong )mod.data[i] * ( ulong )divEstimate; t = u[i]; u[i] -= ( uint )mc; mc >>= 32; if ( u[i] > t ) mc++; i++; } while ( i < resultNum.length ); cc -= ( uint )mc; if ( cc != 0 ) { uint sc = 0, j = 0; uint[] s = mod.data; do { uint a = s[j]; if ( ( ( a += sc ) < sc ) | ( ( u[j] -= a ) > ~a ) ) sc = 1; else sc = 0; j++; } while ( j < resultNum.length ); cc -= sc; } while ( resultNum >= mod ) Kernel.MinusEq(resultNum, mod); } else { while ( resultNum >= mod ) Kernel.MinusEq(resultNum, mod); } } } } while ( pos-- > 0 ); return resultNum; }
public BigInteger EvenPow( BigInteger b, BigInteger exp ) { BigInteger resultNum = new BigInteger(( BigInteger )1, mod.length << 1); BigInteger tempNum = new BigInteger(b % mod, mod.length << 1); // ensures (tempNum * tempNum) < m^ (2k) uint totalBits = ( uint )exp.BitCount(); uint[] wkspace = new uint[mod.length << 1]; // perform squaring and multiply exponentiation for ( uint pos = 0; pos < totalBits; pos++ ) { if ( exp.TestBit(pos) ) { Array.Clear(wkspace, 0, wkspace.Length); Kernel.Multiply(resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0); resultNum.length += tempNum.length; uint[] t = wkspace; wkspace = resultNum.data; resultNum.data = t; BarrettReduction(resultNum); } Kernel.SquarePositive(tempNum, ref wkspace); BarrettReduction(tempNum); if ( tempNum == 1 ) { return resultNum; } } return resultNum; }