/** * Karazuba multiplication */ private BigDecimalPolynomial multRecursive(BigDecimalPolynomial poly2) { decimal[] a = coeffs; decimal[] b = poly2.coeffs; int n = poly2.coeffs.Length; if (n <= 1) { decimal[] c = (decimal[])coeffs.Clone(); for (int i = 0; i < coeffs.Length; i++) { c[i] = decimal.Multiply(c[i], poly2.coeffs[0]); } return(new BigDecimalPolynomial(c)); } else { int n1 = n / 2; BigDecimalPolynomial a1 = new BigDecimalPolynomial(copyOf(a, n1)); BigDecimalPolynomial a2 = new BigDecimalPolynomial(copyOfRange(a, n1, n)); BigDecimalPolynomial b1 = new BigDecimalPolynomial(copyOf(b, n1)); BigDecimalPolynomial b2 = new BigDecimalPolynomial(copyOfRange(b, n1, n)); BigDecimalPolynomial A = (BigDecimalPolynomial)a1.Clone(); A.Add(a2); BigDecimalPolynomial B = (BigDecimalPolynomial)b1.Clone(); B.Add(b2); BigDecimalPolynomial c1 = a1.multRecursive(b1); BigDecimalPolynomial c2 = a2.multRecursive(b2); BigDecimalPolynomial c3 = A.multRecursive(B); c3.Sub(c1); c3.Sub(c2); BigDecimalPolynomial c = new BigDecimalPolynomial(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] = decimal.Add(c.coeffs[n1 + i], (c3.coeffs[i])); } for (int i = 0; i < c2.coeffs.Length; i++) { c.coeffs[2 * n1 + i] = decimal.Add(c.coeffs[2 * n1 + i], (c2.coeffs[i])); } return(c); } }
/** * Subtracts another polynomial which can have a different number of coefficients. * * @param b */ void Sub(BigDecimalPolynomial b) { if (b.coeffs.Length > coeffs.Length) { int N = coeffs.Length; coeffs = copyOf(coeffs, b.coeffs.Length); for (int i = N; i < coeffs.Length; i++) { coeffs[i] = ZERO; } } for (int i = 0; i < b.coeffs.Length; i++) { coeffs[i] = decimal.Subtract(coeffs[i], b.coeffs[i]); } }
/** * Divides each coefficient by a <code>BigDecimal</code> and rounds the result to <code>decimalPlaces</code> places. * * @param divisor the number to divide by * @param decimalPlaces the number of fractional digits to round the result to * @return a new <code>BigDecimalPolynomial</code> */ public BigDecimalPolynomial Divide(decimal divisor, int decimalPlaces) { BigInteger max = MaxCoeffAbs(); int coeffLength = (int)(max.BitLength * LOG_10_2) + 1; // factor = 1/divisor decimal factor = decimal.Round(decimal.Divide(Constants.BIGDEC_ONE, divisor), coeffLength + decimalPlaces + 1, MidpointRounding.AwayFromZero); //decimal.ROUND_HALF_EVEN); // multiply each coefficient by factor BigDecimalPolynomial p = new BigDecimalPolynomial(coeffs.Length); for (int i = 0; i < coeffs.Length; i++) // multiply, then truncate after decimalPlaces so subsequent operations aren't slowed down { p.coeffs[i] = decimal.Round(decimal.Multiply(new decimal(coeffs[i].IntValue), factor), decimalPlaces, MidpointRounding.AwayFromZero); // BigDecimal.ROUND_HALF_EVEN); } return(p); }
/** * Multiplies the polynomial by another, taking the indices mod N. Does not * change this polynomial but returns the result as a new polynomial. * * @param poly2 the polynomial to multiply by * @return a new polynomial */ public BigDecimalPolynomial Multiply(BigDecimalPolynomial poly2) { int N = coeffs.Length; if (poly2.coeffs.Length != N) { throw new InvalidOperationException("Number of coefficients must be the same"); } BigDecimalPolynomial c = multRecursive(poly2); if (c.coeffs.Length > N) { for (int k = N; k < c.coeffs.Length; k++) { c.coeffs[k - N] = decimal.Add(c.coeffs[k - N], c.coeffs[k]); } c.coeffs = copyOf(c.coeffs, N); } return(c); }