public void SquareModP(ulong[] inputOutput) { AsmX64Operations.KaratsubaSquare(inputOutput, temporary2x, N, temporaryKaratsubaBuffer); this.GetModFriendlyPrime(temporary2x); for (int i = N; --i >= 0;) { inputOutput[i] = temporary2x[i]; } }
public static bool UnitTest() { Random random = new Random(101); int n = 2048 / 64; ulong[] a = new ulong[n]; ulong[] b = new ulong[n]; ulong[] m = new ulong[n]; ulong[] am1 = new ulong[n]; ulong[] am3 = new ulong[n]; ulong[] c1 = new ulong[n * 2]; ulong[] c2 = new ulong[n * 2]; ulong[] c3 = new ulong[n * 2]; ulong[] s0 = new ulong[n * 2]; ulong[] s1 = new ulong[n * 2]; ulong[] s2 = new ulong[n * 2]; BigInteger a0, b0, m0; TimeSpan elapsedMontgomeryExpMod = TimeSpan.Zero, elapsedExpMod = TimeSpan.Zero, elapsedBigIntegerExpMod = TimeSpan.Zero; bool ok = true; for (int iteration = 1; --iteration >= 0;) { getRandom(a, random); getRandom(b, random); getRandom(m, random); m[0] &= ulong.MaxValue - 1; a0 = new BigInteger(a.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray()); b0 = new BigInteger(b.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray()); m0 = new BigInteger(m.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray()); a.CopyTo(am1, 0); ExpMod(am1, b, m, n, 5); BigInteger am2 = BigInteger.Zero; elapsedBigIntegerExpMod += MeasureTime(() => { am2 = BigInteger.ModPow(a0, b0, m0); }); var bytes1 = am1.SelectMany(l => BitConverter.GetBytes(l)).ToArray(); var bytes2 = am2.ToByteArray(); ok &= Enumerable.Range(0, Math.Min(bytes1.Length, bytes2.Length)).All(idx => bytes1[idx] == bytes2[idx]); } for (int iteration = 1; --iteration >= 0;) { getRandom(a, random); getRandom(b, random); getRandom(m, random); m[0] |= 1; a.CopyTo(am1, 0); a.CopyTo(am3, 0); elapsedMontgomeryExpMod += MeasureTime(() => { MontgomeryExpMod(am1, b, m, n, 6); }); elapsedExpMod += MeasureTime(() => { ExpMod(am3, b, m, n, 5); }); ok &= Enumerable.Range(0, n).All(idx => am3[idx] == am1[idx]); } TimeSpan elapsedMulDirect = TimeSpan.Zero, elapsedKaratsuba = TimeSpan.Zero; ulong[] temporaryKaratsubaBuffer = new ulong[GetKaratsubaMultiplicationBufferSize(n)]; for (int iteration = 128; --iteration >= 0;) { getRandom(a, random); getRandom(b, random); AsmX64Operations.Multiply(a, a, s0, n); elapsedMulDirect += MeasureTime(() => { AsmX64Operations.Multiply(a, b, c1, n); AsmX64Operations.Square(a, s1, n); }); elapsedKaratsuba += MeasureTime(() => { AsmX64Operations.Karatsuba(a, b, c2, n, temporaryKaratsubaBuffer); AsmX64Operations.KaratsubaSquare(a, s2, n, temporaryKaratsubaBuffer); }); ok &= Enumerable.Range(0, n * 2).All(idx => c1[idx] == c2[idx]); ok &= Enumerable.Range(0, n * 2).All(idx => s0[idx] == s1[idx]); ok &= Enumerable.Range(0, n * 2).All(idx => s1[idx] == s2[idx]); } if (!ok) { //MessageBox.Show("not ok - error"); return(false); } //MessageBox.Show( // "elapsedMontgomeryExpMod: " + elapsedMontgomeryExpMod.ToString() + "\r\n" + // "elapsedExpMod: " + elapsedExpMod.ToString() + "\r\n" + // "elapsedBigIntegerExpMod: " + elapsedBigIntegerExpMod.ToString() + "\r\n" + // "normal: " + elapsedMulDirect.ToString() + " karatsuba: " + elapsedKaratsuba.ToString()); return(true); }