/// <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); }
void IXmlSerializable.ReadXml(XmlReader reader) { string value = reader.ReadInnerXml(); CPolynomial poly = Parse(value, CultureInfo.InvariantCulture); _coeffs = poly._coeffs; }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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(); }
/// <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); }
/// <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); }
/// <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)); }
/// <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)); }