示例#1
0
            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();
            }
示例#2
0
        /// <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);
        }