public new IntegerPolynomial Multiply(IntegerPolynomial poly2, int modulus) { // even on 32-bit systems, LongPolynomial5 multiplies faster than IntegerPolynomial if (modulus == 2048) { IntegerPolynomial poly2Pos = (IntegerPolynomial)poly2.Clone(); poly2Pos.ModPositive(2048); LongPolynomial5 poly5 = new LongPolynomial5(poly2Pos); return(poly5.Multiply(this).ToIntegerPolynomial()); } else { return(base.Multiply(poly2, modulus)); } }
/** * Karazuba multiplication */ private IntegerPolynomial MultiplyRecursive(IntegerPolynomial poly2) { int[] a = coeffs; int[] b = poly2.coeffs; int n = poly2.coeffs.Length; if (n <= 32) { int cn = 2 * n - 1; IntegerPolynomial c = new IntegerPolynomial(new int[cn]); for (int k = 0; k < cn; k++) { for (int i = System.Math.Max(0, k - n + 1); i <= System.Math.Min(k, n - 1); i++) { c.coeffs[k] += b[i] * a[k - i]; } } return(c); } else { int n1 = n / 2; int[] a1temp = new int[n1]; int[] a2temp = new int[n - n1]; int[] b1temp = new int[n1]; int[] b2temp = new int[n - n1]; Array.Copy(a, a1temp, n1); Array.Copy(a, n1, a2temp, 0, n - n1); Array.Copy(b, b1temp, n1); Array.Copy(b, n1, b2temp, 0, n - n1); IntegerPolynomial a1 = new IntegerPolynomial(a1temp); IntegerPolynomial a2 = new IntegerPolynomial(a2temp); IntegerPolynomial b1 = new IntegerPolynomial(b1temp); IntegerPolynomial b2 = new IntegerPolynomial(b2temp); IntegerPolynomial A = (IntegerPolynomial)a1.Clone(); A.Add(a2); IntegerPolynomial B = (IntegerPolynomial)b1.Clone(); B.Add(b2); IntegerPolynomial c1 = a1.MultiplyRecursive(b1); IntegerPolynomial c2 = a2.MultiplyRecursive(b2); IntegerPolynomial c3 = A.MultiplyRecursive(B); c3.Sub(c1); c3.Sub(c2); IntegerPolynomial c = new IntegerPolynomial(2 * n - 1); for (int i = 0; i < c1.coeffs.Length; i++) { c.coeffs[i] = c1.coeffs[i]; } for (int i = 0; i < c3.coeffs.Length; i++) { c.coeffs[n1 + i] += c3.coeffs[i]; } for (int i = 0; i < c2.coeffs.Length; i++) { c.coeffs[2 * n1 + i] += c2.coeffs[i]; } return(c); } }