/** * Multiplies the polynomial by another, taking the indices mod N. Does not change this polynomial * but returns the result as a new polynomial.<br> * Both polynomials must have the same number of coefficients. * * @param poly2 the polynomial to multiply by * @return a new polynomial */ public BigIntPolynomial mult(BigIntPolynomial poly2) { int N = coeffs.length; if (poly2.coeffs.length != N) { throw new IllegalArgumentException("Number of coefficients must be the same"); } BigIntPolynomial c = multRecursive(poly2); if (c.coeffs.length > N) { for (int k = N; k < c.coeffs.length; k++) { c.coeffs[k - N] = c.coeffs[k - N].add(c.coeffs[k]); } c.coeffs = Arrays.copyOf(c.coeffs, N); } return c; }
/** Karazuba multiplication */ private BigIntPolynomial multRecursive(BigIntPolynomial poly2) { BigInteger[] a = coeffs; BigInteger[] b = poly2.coeffs; int n = poly2.coeffs.length; if (n <= 1) { BigInteger[] c = Arrays.clone(coeffs); for (int i = 0; i < coeffs.length; i++) { c[i] = c[i].multiply(poly2.coeffs[0]); } return new BigIntPolynomial(c); } else { int n1 = n / 2; BigIntPolynomial a1 = new BigIntPolynomial(Arrays.copyOf(a, n1)); BigIntPolynomial a2 = new BigIntPolynomial(Arrays.copyOfRange(a, n1, n)); BigIntPolynomial b1 = new BigIntPolynomial(Arrays.copyOf(b, n1)); BigIntPolynomial b2 = new BigIntPolynomial(Arrays.copyOfRange(b, n1, n)); BigIntPolynomial A = (BigIntPolynomial) a1.clone(); A.add(a2); BigIntPolynomial B = (BigIntPolynomial) b1.clone(); B.add(b2); BigIntPolynomial c1 = a1.multRecursive(b1); BigIntPolynomial c2 = a2.multRecursive(b2); BigIntPolynomial c3 = A.multRecursive(B); c3.sub(c1); c3.sub(c2); BigIntPolynomial c = new BigIntPolynomial(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] = c.coeffs[n1 + i].add(c3.coeffs[i]); } for (int i = 0; i < c2.coeffs.length; i++) { c.coeffs[2 * n1 + i] = c.coeffs[2 * n1 + i].add(c2.coeffs[i]); } return c; } }