// this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) private BigInteger Exponential(long e, IExponential z) { if (e > 0xffffffff || e < 1) { return(One); } var result = new BigInteger(); var result2 = new BigInteger(); var g = z.Convert(this); var i = NumberOfBits((int)e) - 1; g.CopyTo(result); while (--i >= 0) { z.SquareTo(result, result2); if ((e & (1 << i)) > 0) { z.MultiplyTo(result2, g, result); } else { var temp = result; result = result2; result2 = temp; } } return(z.Revert(result)); }
// this^e % m (HAC 14.85) public BigInteger ModuloPower(BigInteger e, BigInteger m) { var i = e.BitLength; var k = 0; var result = ValueOf(1); IExponential z = null; if (i <= 0) { return(result); } if (i < 18) { k = 1; } else if (i < 48) { k = 3; } else if (i < 144) { k = 4; } else if (i < 768) { k = 5; } else { k = 6; } if (i < 8) { z = new ClassicExponential(m); } else if (m.IsEven) { z = new BarrettExponential(m); } else { z = new MontgomeryExponential(m); } // precomputation var g = new BigInteger[2]; var n = 3; var k1 = k - 1; var km = (1 << k) - 1; g[1] = z.Convert(this); if (k > 1) { var g2 = new BigInteger(); z.SquareTo(g[1], g2); while (n <= km) { if (n + 1 > g.Length) { Array.Resize(ref g, n + 1); } g[n] = new BigInteger(); z.MultiplyTo(g2, g[n - 2], g[n]); n += 2; } } var j = e.t - 1; var isFirstIteration = true; var result2 = new BigInteger(); i = NumberOfBits(e[j]) - 1; while (j >= 0) { var w = 0; if (i >= k1) { w = (e[j] >> (i - k1)) & km; } else { w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i); if (j > 0) { w |= e[j - 1] >> (DB + i - k1); } } n = k; while ((w & 1) == 0) { w = w >> 1; n--; } if ((i -= n) < 0) { i += DB; j--; } if (isFirstIteration) // ret == 1, don't bother squaring or multiplying it { g[w].CopyTo(result); isFirstIteration = false; } else { while (n > 1) { z.SquareTo(result, result2); z.SquareTo(result2, result); n -= 2; } if (n > 0) { z.SquareTo(result, result2); } else { var temp = result; result = result2; result2 = temp; } z.MultiplyTo(result2, g[w], result); } while (j >= 0 && (e[j] & (1 << i)) == 0) { z.SquareTo(result, result2); var temp = result; result = result2; result2 = temp; if (--i < 0) { i = DB - 1; j--; } } } return(z.Revert(result)); }