예제 #1
0
        /// <summary>
        /// Subtracts one complex polynomial from another.
        /// </summary>
        /// <param name="poly1">The first complex polynomial.</param>
        /// <param name="poly2">The second complex polynomial.</param>
        /// <returns>The result of subtracting poly2 from poly1.</returns>
        public static CPolynomial Subtract(CPolynomial poly1, CPolynomial poly2)
        {
            int len1 = poly1.Degree + 1;
            int len2 = poly2.Degree + 1;

            int maxLen = Math.Max(len1, len2);
            int minLen = Math.Min(len1, len2);

            CPolynomial result = new CPolynomial(maxLen);

            for (int i = 0; i < minLen; i++)
            {
                result[i] = poly1[i] - poly2[i];
            }

            if (len1 == maxLen)
            {
                for (int i = minLen; i < maxLen; i++)
                {
                    result[i] = poly1[i];
                }
            }
            else
            {
                for (int i = minLen; i < maxLen; i++)
                {
                    result[i] = -poly2[i];
                }
            }

            return(result);
        }
예제 #2
0
        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            string      value = reader.ReadInnerXml();
            CPolynomial poly  = Parse(value, CultureInfo.InvariantCulture);

            _coeffs = poly._coeffs;
        }
예제 #3
0
        /// <summary>
        /// Divides two complex polynomials.
        /// </summary>
        /// <param name="poly1">The first complex polynomial.</param>
        /// <param name="poly2">The second complex polynomial.</param>
        /// <param name="remainder">Remainder of division of the first polynomial in the second.</param>
        /// <returns>Quotient of division of poly1 on poly2.</returns>
        /// <exception cref="System.DivideByZeroException">The polynomial poly2 is zero.</exception>
        public static CPolynomial Divide(CPolynomial poly1, CPolynomial poly2, out CPolynomial remainder)
        {
            int len1 = poly1.Degree + 1;
            int len2 = poly2.Degree + 1;

            CPolynomial q = new CPolynomial(len1 - len2 + 1);
            CPolynomial r = Clean(poly1);
            Complex     a = poly2[len2 - 1];

            for (int i = q.Length - 1; i >= 0; i--)
            {
                q[i] = r[r.Length - 1] / a;

                CPolynomial rt = new CPolynomial(r.Length - 1);

                for (int j = rt.Length - 1, k = len2 - 2; j > rt.Length - len2; j--, k--)
                {
                    rt[j] = r[j] - q[i] * poly2[k];
                }

                for (int j = rt.Length - len2; j >= 0; j--)
                {
                    rt[j] = r[j];
                }

                r = rt;
            }

            remainder = r;
            return(q);
        }
예제 #4
0
        /// <summary>
        /// Returns the remainder of dividing the first polynomial in the second.
        /// </summary>
        /// <param name="poly1">The first complex polynomial.</param>
        /// <param name="poly2">The second complex polynomial.</param>
        /// <returns>The remainder of the division poly1 to poly2.</returns>
        public static CPolynomial Modulus(CPolynomial poly1, CPolynomial poly2)
        {
            CPolynomial remainder;

            Divide(poly1, poly2, out remainder);
            return(remainder);
        }
예제 #5
0
        /// <summary>
        /// Divides a complex polynomial by a scalar.
        /// </summary>
        /// <param name="poly">A complex polynomial.</param>
        /// <param name="number">A complex number.</param>
        /// <returns>The result of dividing poly by number.</returns>
        /// <exception cref="System.DivideByZeroException">The number is zero.</exception>
        public static CPolynomial Divide(CPolynomial poly, Complex number)
        {
            CPolynomial result = new CPolynomial(poly.Degree + 1);

            for (int i = 0; i < result.Length; i++)
            {
                result[i] = poly[i] / number;
            }

            return(result);
        }
예제 #6
0
        /// <summary>
        /// Returns the complex polynomial without leading zeros.
        /// </summary>
        /// <param name="poly">A complex polynomial.</param>
        /// <returns>The poly without leading zeros.</returns>
        public static CPolynomial Clean(CPolynomial poly)
        {
            CPolynomial result = new CPolynomial(poly.Degree + 1);

            for (int i = 0; i < result.Length; i++)
            {
                result[i] = poly[i];
            }

            return(result);
        }
예제 #7
0
        /// <summary>
        /// Returns the normalized complex polynomial.
        /// </summary>
        /// <returns>The normalized complex polynomial.</returns>
        public CPolynomial Normalize()
        {
            CPolynomial result  = new CPolynomial(Degree + 1);
            Complex     divisor = _coeffs[result.Length - 1];

            for (int i = 0; i < result.Length; i++)
            {
                result[i] = _coeffs[i] / divisor;
            }

            return(result);
        }
예제 #8
0
        /// <summary>
        /// Returns the antiderivative of the complex polynomial.
        /// </summary>
        /// <returns>The antiderivative of this instance.</returns>
        public CPolynomial Antiderivative()
        {
            int         len    = Degree + 1;
            CPolynomial result = new CPolynomial(len + 1);

            for (int i = 1; i < result.Length; i++)
            {
                result[i] = _coeffs[i - 1] / i;
            }

            return(result);
        }
예제 #9
0
        /// <summary>
        /// Divides a complex polynomial by a binomial of the form (x - c).
        /// </summary>
        /// <param name="poly">A complex polynomial.</param>
        /// <param name="c">A binomial coefficient in the constant term.</param>
        /// <param name="remainder">Remainder of division of the polynomial in the binomial.</param>
        /// <returns>Quotient of division of poly on the binomial (x - c).</returns>
        public static CPolynomial DivBinom(CPolynomial poly, Complex c, out Complex remainder)
        {
            int         len    = poly.Degree + 1;
            CPolynomial result = new CPolynomial(len - 1);

            remainder = poly[len - 1];

            for (int i = result.Length - 1; i >= 0; i--)
            {
                result[i] = remainder;
                remainder = remainder * c + poly[i];
            }

            return(result);
        }
예제 #10
0
        /// <summary>
        /// Returns the second derivative of the complex polynomial.
        /// </summary>
        /// <returns>The second derivative of this instance.</returns>
        public CPolynomial SecondDerivative()
        {
            int len = Degree + 1;

            if (len <= 2)
            {
                return(new CPolynomial(1));
            }
            CPolynomial result = new CPolynomial(len - 2);

            for (int i = 2; i < len; i++)
            {
                result[i - 2] = this[i] * i * (i - 1);
            }

            return(result);
        }
예제 #11
0
        /// <summary>
        /// Returns the first derivative of the complex polynomial.
        /// </summary>
        /// <returns>The first derivative of this instance.</returns>
        public CPolynomial FirstDerivative()
        {
            int len = Degree + 1;

            if (len <= 1)
            {
                return(new CPolynomial(1));
            }
            CPolynomial result = new CPolynomial(len - 1);

            for (int i = 1; i < len; i++)
            {
                result[i - 1] = this[i] * i;
            }

            return(result);
        }
예제 #12
0
        /// <summary>
        /// Returns a complex polynomial that has the specified roots.
        /// </summary>
        /// <param name="roots">An array of complex roots.</param>
        /// <returns>The complex polynomial with the specified roots.</returns>
        public static CPolynomial FromRoots(IList <Complex> roots)
        {
            int         n      = roots.Count;
            CPolynomial result = new CPolynomial(n + 1);

            result[n] = 1.0;

            for (int i = 0; i < n; i++)
            {
                for (int j = n - i - 1; j < n; j++)
                {
                    result[j] = result[j] - roots[i] * result[j + 1];
                }
            }

            return(result);
        }
예제 #13
0
        /// <summary>
        /// Multiplies two complex polynomials.
        /// </summary>
        /// <param name="poly1">The first complex polynomial.</param>
        /// <param name="poly2">The second complex polynomial.</param>
        /// <returns>The product of poly1 and poly2.</returns>
        public static CPolynomial Multiply(CPolynomial poly1, CPolynomial poly2)
        {
            int len1 = poly1.Degree + 1;
            int len2 = poly2.Degree + 1;

            CPolynomial result = new CPolynomial(len1 + len2 - 1);

            for (int i = 0; i < len1; i++)
            {
                for (int j = 0; j < len2; j++)
                {
                    result[i + j] += poly1[i] * poly2[j];
                }
            }

            return(result);
        }
예제 #14
0
        /// <summary>
        /// Returns the value indicating whether two instances of complex polynomial are equal.
        /// </summary>
        /// <param name="poly1">The first complex polynomial to compare.</param>
        /// <param name="poly2">The second complex polynomial to compare.</param>
        /// <returns>True if the poly1 and poly2 parameters have the same value; otherwise, false.</returns>
        public static bool Equals(CPolynomial poly1, CPolynomial poly2)
        {
            if (poly1.Degree != poly2.Degree)
            {
                return(false);
            }

            int len = poly1.Degree + 1;

            for (int i = 0; i < len; i++)
            {
                if (poly1[i] != poly2[i])
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #15
0
        /// <summary>
        /// Returns the interpolating polynomial through a set of nodes using the Lagrange method.
        /// </summary>
        /// <param name="xValues">
        /// A real array containing the x-coordinates of interpolation nodes.
        /// The elements of this array must be distinct.
        /// </param>
        /// <param name="yValues">
        /// A real array containing the y-coordinates of interpolation nodes.
        /// </param>
        /// <returns>The interpolating polynomial for the specified nodes.</returns>
        /// <exception cref="System.ArgumentException">The arrays xValues and yValues have different lengths.</exception>
        public static CPolynomial InterpolatingPolynomial(IList <double> xValues, IList <double> yValues)
        {
            if (xValues.Count != yValues.Count)
            {
                throw new ArgumentException("The arrays of abscissas and ordinates have different lengths.");
            }

            int n = xValues.Count;

            CPolynomial L = new CPolynomial(n);

            for (int i = 0; i < n; i++)
            {
                CPolynomial l = new CPolynomial(n);
                l[n - 1] = 1;

                Complex denom = 1;

                for (int j = 0; j < n; j++)
                {
                    if (j != i)
                    {
                        int k = (j > i) ? n - j - 1 : n - j - 2;

                        for (; k < n - 1; k++)
                        {
                            l[k] = l[k] - xValues[j] * l[k + 1];
                        }

                        denom *= (xValues[i] - xValues[j]);
                    }
                }

                Complex factor = yValues[i] / denom;

                for (int j = 0; j < n; j++)
                {
                    L[j] += factor * l[j];
                }
            }

            return(L);
        }
예제 #16
0
        /// <summary>
        /// Returns the n-th derivative of the complex polynomial.
        /// </summary>
        /// <param name="order">An order of derivative.</param>
        /// <returns>The n-th derivative of this instance.</returns>
        public CPolynomial NthDerivative(int order)
        {
            int len = Degree + 1;

            if (len <= order)
            {
                return(new CPolynomial(1));
            }
            CPolynomial result = new CPolynomial(len - order);

            for (int i = order; i < len; i++)
            {
                int exp = 1, k = i;
                for (int j = 0; j < order; j++)
                {
                    exp *= k--;
                }

                result[i - order] = this[i] * exp;
            }

            return(result);
        }
예제 #17
0
 /// <summary>
 /// Initializes a complex polynomial from another instance of a complex polynomial.
 /// </summary>
 /// <param name="poly">A complex polynomial.</param>
 public CPolynomial(CPolynomial poly)
 {
     _coeffs = (Complex[])poly._coeffs.Clone();
 }
예제 #18
0
        /// <summary>
        /// Converts string representation of a polynomial
        /// in a specified culture-specific format to its complex polynomial equivalent.
        /// </summary>
        /// <param name="s">A string containing a complex polynomial to convert.</param>
        /// <param name="provider">An System.IFormatProvider that supplies culture-specific formatting information about s.</param>
        /// <returns>A complex polynomial equivalent to the value specified in s.</returns>
        /// <exception cref="System.ArgumentNullException">The string s is null.</exception>
        /// <exception cref="System.ArgumentException">The string s is empty string.</exception>
        /// <exception cref="System.FormatException">The string s is not a polynomial in a valid format.</exception>
        public static CPolynomial Parse(string s, IFormatProvider provider)
        {
            if (s == null)
            {
                throw new ArgumentNullException(Properties.Resources.EXC_STRING_NOT_NULL);
            }

            string str = s.Trim();

            if (String.IsNullOrEmpty(str))
            {
                throw new ArgumentException(Properties.Resources.EXC_STRING_NOT_EMPTY);
            }

            string varName = String.Empty;

            Match matchAll = _polyRegex.Match(str);

            if (!matchAll.Success)
            {
                throw new FormatException(Properties.Resources.EXC_POLY_INCCORECT_FORMAT);
            }

            Dictionary <int, Complex> p = new Dictionary <int, Complex>();

            int maxExp = 0;

            foreach (Capture capture in matchAll.Groups["term"].Captures)
            {
                Match match = _polyPartRegex.Match(capture.Value.Trim());

                if (!String.IsNullOrEmpty(match.Value))
                {
                    string sign_s = match.Groups["sign"].Value;
                    string coef_s = match.Groups["num"].Value;
                    string var_s  = match.Groups["var"].Value;
                    string exp_s  = match.Groups["exp"].Value;

                    if (!String.IsNullOrEmpty(var_s))
                    {
                        if (String.IsNullOrEmpty(varName))
                        {
                            varName = var_s;
                        }
                        if (varName != var_s)
                        {
                            throw new FormatException(Properties.Resources.EXC_POLY_MISMATCH_VAR_NAMES);
                        }
                    }

                    int     sign = int.Parse(sign_s + 1, provider);
                    Complex coef = !String.IsNullOrEmpty(coef_s) ? sign * Complex.Parse(coef_s, provider) : sign;
                    int     exp  = !String.IsNullOrEmpty(exp_s) ? int.Parse(exp_s, provider) : 0;

                    if (!String.IsNullOrEmpty(var_s) && String.IsNullOrEmpty(exp_s))
                    {
                        exp = 1;
                    }

                    if (maxExp < exp)
                    {
                        maxExp = exp;
                    }

                    if (p.ContainsKey(exp))
                    {
                        p[exp] += coef;
                    }
                    else
                    {
                        p.Add(exp, coef);
                    }
                }
            }

            // Need to find the maximum degree and put here
            CPolynomial poly = new CPolynomial(maxExp + 1);

            foreach (KeyValuePair <int, Complex> pair in p.OrderBy(x => x.Key))
            {
                poly[pair.Key] = pair.Value;
            }

            return(poly);
        }
예제 #19
0
        /// <summary>
        /// Returns a vector of approximate values of roots of a complex polynomial by Laguerre's method.
        /// </summary>
        /// <param name="poly">A complex polynomial.</param>
        /// <returns>The approximate values of roots of poly.</returns>
        /// <exception cref="System.ArgumentException">
        /// Number of elements in poly is less than 2 or more than 99.
        /// </exception>
        public static Complex[] LaguerreRoots(CPolynomial poly)
        {
            const int maxIters    = 100;
            const int maxAttempts = 10;

            // Remove zero elements standing at the end.
            int lidx = 0;
            int ridx = poly.Length - 1;

            while (ridx >= 0 && poly[ridx] == Complex.Zero)
            {
                ridx--;
            }
            while (lidx < poly.Length && poly[lidx] == Complex.Zero)
            {
                lidx++;
            }
            int length = ridx + 1;

            if (length < 2 || length > 99)
            {
                throw new ArgumentException("Number of coefficients must be between 1 and 100.");
            }

            int rootsCount = length - 1;

            Complex[] roots = new Complex[rootsCount];

            CPolynomial div = new CPolynomial(ridx - lidx + 1);

            for (int i = lidx; i <= ridx; i++)
            {
                div[i - lidx] = poly[i];
            }

            Random rand = new Random(0);

            // Main loop
            for (int i = 0; i < ridx - lidx; i++)
            {
                Complex a = rand.Next(-1000, 1000);
                if (a == 0)
                {
                    a = 1;
                }
                Complex a_old       = a + 1;
                int     currIter    = 0;
                int     currAttempt = 0;

                // Degree of the div polynomial
                int n = div.Length - 1;

                while (!NumericUtil.FuzzyEquals(a, a_old, Machine.Epsilon))
                {
                    if (currIter > maxIters)
                    {
                        a = rand.Next(-1000, 1000);
                        if (a == 0)
                        {
                            a = 1;
                        }
                        a_old    = a + 1;
                        currIter = 0;
                        currAttempt++;

                        if (currAttempt > maxAttempts)
                        {
                            throw new NotConvergenceException();
                        }

                        continue;
                    }

                    currIter++;

                    Complex p   = div.Evaluate(a);
                    Complex dp  = div.FirstDerivative(a);
                    Complex d2p = div.SecondDerivative(a);

                    if (Complex.Abs(p) <= Machine.Epsilon)
                    {
                        break;
                    }

                    Complex G = dp / p;
                    Complex H = G * G - d2p / p;

                    Complex D     = Complex.Sqrt((n - 1) * (n * H - G * G));
                    Complex denom = Complex.Abs(G + D) >= Complex.Abs(G - D) ? G + D : G - D;
                    if (denom == Complex.Zero)
                    {
                        denom = Machine.Epsilon;
                    }

                    a_old = a;
                    a     = a - n / denom;
                }

                roots[i] = a;

                Complex rem;
                div = DivBinom(div, a, out rem);
            }

            Array.Sort <Complex>(roots, new ComplexComparer());
            return(roots);
        }
예제 #20
0
 /// <summary>
 /// Returns a value indicating whether this instance is equal to a specified
 /// complex polynomial.
 /// </summary>
 /// <param name="obj">A CPolynomial object to compare to this instance.</param>
 /// <returns>True if obj is equal to this instance; otherwise, false.</returns>
 public bool Equals(CPolynomial obj)
 {
     return(Equals(this, obj));
 }
예제 #21
0
        /// <summary>
        /// Divides two complex polynomials.
        /// </summary>
        /// <param name="poly1">The first complex polynomial.</param>
        /// <param name="poly2">The second complex polynomial.</param>
        /// <returns>Quotient of division of poly1 on poly2.</returns>
        /// <exception cref="System.DivideByZeroException">The polynomial poly2 is zero.</exception>
        public static CPolynomial Divide(CPolynomial poly1, CPolynomial poly2)
        {
            CPolynomial remainder;

            return(Divide(poly1, poly2, out remainder));
        }