public void Multiply(PolynomialFactor factor) { var len = Coefficients.Count; Coefficients.AddRange(factor.Coefficients); PolynomialMultiplication(0, len, len, factor.Coefficients.Count, 0, 1, 1); for (var i = 0; i < Coefficients.Count; ++i) { Coefficients[i] = Destination[i]; } SetKey(); }
/// <summary> /// Computes the coefficients of a real monic polynomial given its real and complex roots. /// The final monic polynomial is represented as: /// coefficients[0] + coefficients[1] * X + coefficients[2] * X^2 + ... + coefficients[n-1] * X^(n-1) + X^n /// /// Note: the constant 1 coefficient of the highest degree term is implicit and not included in the output of the method. /// </summary> /// <param name="roots">The input (complex) roots</param> /// <param name="coefficients">The output real coefficients</param> /// <returns>A boolean flag indicating whether the algorithm was successful.</returns> public static bool FindPolynomialCoefficients(Complex[] roots, ref Double[] coefficients) { Contracts.CheckParam(Utils.Size(roots) > 0, nameof(roots), "There must be at least 1 input root."); int i; int n = roots.Length; var hash = new Dictionary <Complex, FactorMultiplicity>(); int destinationOffset = 0; var factors = new List <PolynomialFactor>(); for (i = 0; i < n; ++i) { if (Double.IsNaN(roots[i].Real) || Double.IsNaN(roots[i].Imaginary)) { return(false); } if (roots[i].Equals(Complex.Zero)) // Zero roots { destinationOffset++; } else if (roots[i].Imaginary == 0) // Real roots { var f = new PolynomialFactor(new[] { (decimal) - roots[i].Real }); factors.Add(f); } else // Complex roots { var conj = Complex.Conjugate(roots[i]); FactorMultiplicity temp; if (hash.TryGetValue(conj, out temp)) { temp.Multiplicity--; var f = new PolynomialFactor(new[] { (decimal)(roots[i].Real * roots[i].Real + roots[i].Imaginary * roots[i].Imaginary), (decimal)(-2 * roots[i].Real) }); factors.Add(f); if (temp.Multiplicity <= 0) { hash.Remove(conj); } } else { if (hash.TryGetValue(roots[i], out temp)) { temp.Multiplicity++; } else { hash.Add(roots[i], new FactorMultiplicity()); } } } } if (hash.Count > 0) { return(false); } var comparer = new ByMaximumCoefficient(); factors.Sort(comparer); if (destinationOffset < n - 1) { if (Utils.Size(PolynomialFactor.Destination) < n) { PolynomialFactor.Destination = new decimal[n]; } while (factors.Count > 1) { var k1 = Math.Abs(factors.ElementAt(0).Key); var k2 = Math.Abs(factors.ElementAt(factors.Count - 1).Key); PolynomialFactor f1; if (k1 < k2) { f1 = factors.ElementAt(0); factors.RemoveAt(0); } else { f1 = factors.ElementAt(factors.Count - 1); factors.RemoveAt(factors.Count - 1); } var ind = factors.BinarySearch(new PolynomialFactor(-f1.Key), comparer); if (ind < 0) { ind = ~ind; } ind = Math.Min(factors.Count - 1, ind); var f2 = factors.ElementAt(ind); factors.RemoveAt(ind); f1.Multiply(f2); ind = factors.BinarySearch(f1, comparer); if (ind >= 0) { factors.Insert(ind, f1); } else { factors.Insert(~ind, f1); } } } if (Utils.Size(coefficients) < n) { coefficients = new Double[n]; } for (i = 0; i < destinationOffset; ++i) { coefficients[i] = 0; } if (destinationOffset < n) { var coeff = factors.ElementAt(0).Coefficients; for (i = destinationOffset; i < n; ++i) { coefficients[i] = Decimal.ToDouble(coeff[i - destinationOffset]); } } return(true); }