public static bool UnitTest(int seed) { Random random = new Random(seed); int bits = 17; int n = 1 << bits; FourierPoint[] a0 = new FourierPoint[n]; FourierPoint[] a1 = new FourierPoint[n]; byte[] bytes = new byte[16]; for (int i = n; --i >= 0;) { random.NextBytes(bytes); a0[i] = a1[i] = new FourierPoint(BitConverter.ToUInt64(bytes, 0), BitConverter.ToUInt64(bytes, 8)); } a0.FFT(false); a0.IFFT(false); //var scale = FourierPoint.PowMod(FourierPoint.HalfOne, new FourierPoint((ulong)bits, 0)); for (int i = n; --i >= 0;) { //a0[i] *= scale; a0[i] >>= bits; } for (int i = n; --i >= 0;) { if (a0[i] != a1[i]) { return(false); } } return(true); }
public static void Multiply(ulong[] input1, ulong[] input2, ulong[] result, int n) { // AsmX64Operations.FastestMultiplication(input1, input2, result, n); // return; int fftBitsPerDigit, fftLog2Size; GetFFTParameters(n, out fftBitsPerDigit, out fftLog2Size); long fftN = 1L << fftLog2Size; //double directComputations = (double)n * n; //double karatsubaComputations = 4.7 * Math.Pow(n, LOG2_3); //double fftComputations = 7.2 * (3.0 * fftLog2Size + 4.0) * fftN; FourierPoint[] number1 = new FourierPoint[fftN]; GroupDigits(input1, fftBitsPerDigit, number1); FourierPoint[] number2 = new FourierPoint[fftN]; GroupDigits(input2, fftBitsPerDigit, number2); //FourierPoint scale = FourierPoint.PowMod(FourierPoint.HalfOne, new FourierPoint((ulong)fftLog2Size, 0UL)); number1.FFT(false); number2.FFT(false); for (int i = number1.Length; --i >= 0;) { FourierPoint point = number1[i]; FourierPoint.mulmod(ref point, ref number2[i]); //FourierPoint.mulmod(ref point, ref scale); point >>= fftLog2Size; number1[i] = point; } number1.IFFT(false); var number1Handle = GCHandle.Alloc(number1, GCHandleType.Pinned); try { FourierPoint.PropagateCarries(number1Handle.AddrOfPinnedObject(), fftBitsPerDigit, number1.Length); } finally { number1Handle.Free(); } UngroupDigits(number1, fftBitsPerDigit, result); }