From 610921f6c23ecd3f86c1ccb0b5075de3353af566 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sun, 14 Oct 2018 21:25:55 +0200 Subject: [PATCH] Polynomial: more systematic arithmetics --- src/Numerics/Polynomial.cs | 303 +++++++++++++++++++++++++------------ 1 file changed, 204 insertions(+), 99 deletions(-) diff --git a/src/Numerics/Polynomial.cs b/src/Numerics/Polynomial.cs index edf79b6b..f4bb54dc 100644 --- a/src/Numerics/Polynomial.cs +++ b/src/Numerics/Polynomial.cs @@ -10,7 +10,7 @@ using MathNet.Numerics.LinearAlgebra.Factorization; namespace MathNet.Numerics { /// - /// A single-variable polynomial with real-valued coefficients. + /// A single-variable polynomial with real-valued coefficients and non-negative exponents. /// public class Polynomial { @@ -136,8 +136,8 @@ namespace MathNet.Numerics /// public static Polynomial Fit(double[] x, double[] y, int order, DirectRegressionMethod method = DirectRegressionMethod.QR) { - var pArr = Numerics.Fit.Polynomial(x, y, order, method); - return new Polynomial(pArr); + var coefficients = Numerics.Fit.Polynomial(x, y, order, method); + return new Polynomial(coefficients); } /// @@ -149,19 +149,31 @@ namespace MathNet.Numerics return Numerics.Evaluate.Polynomial(z, Coefficients); } + /// + /// Evaluate a polynomial at point x. + /// + /// The location where to evaluate the polynomial at. + public Complex Evaluate(Complex z) + { + return Numerics.Evaluate.Polynomial(z, Coefficients); + } + /// /// Evaluate a polynomial at points z. /// /// The locations where to evaluate the polynomial at. public IEnumerable Evaluate(IEnumerable z) { - var result = new List(); - foreach (var item in z) - { - result.Add(Evaluate(item)); - } + return z.Select(Evaluate); + } - return result; + /// + /// Evaluate a polynomial at points z. + /// + /// The locations where to evaluate the polynomial at. + public IEnumerable Evaluate(IEnumerable z) + { + return z.Select(Evaluate); } public Polynomial Differentiate() @@ -199,11 +211,87 @@ namespace MathNet.Numerics return p; } + /// + /// Addition of two Polynomials (piecewise) + /// + /// Left polynomial + /// Right polynomial + /// Resulting Polynomial + public static Polynomial operator +(Polynomial a, Polynomial b) + { + return Add(a, b); + } + + /// + /// adds a scalar to a polynomial. + /// + /// Polynomial + /// Scalar value + /// Resulting Polynomial + public static Polynomial operator +(Polynomial a, double k) + { + return Add(a, k); + } + + /// + /// adds a scalar to a polynomial. + /// + /// Scalar value + /// Polynomial + /// Resulting Polynomial + public static Polynomial operator +(double k, Polynomial a) + { + return Add(a, k); + } + + /// + /// Subtraction of two polynomial. + /// + /// Left polynomial + /// Right polynomial + /// Resulting Polynomial + public static Polynomial operator -(Polynomial a, Polynomial b) + { + return Subtract(a, b); + } + + /// + /// Subtracts a scalar from a polynomial. + /// + /// Polynomial + /// Scalar value + /// Resulting Polynomial + public static Polynomial operator -(Polynomial a, double k) + { + return Subtract(a, k); + } + + /// + /// Subtracts a polynomial from a scalar. + /// + /// Scalar value + /// Polynomial + /// Resulting Polynomial + public static Polynomial operator -(double k, Polynomial a) + { + return Subtract(k, a); + } + + /// + /// Negates a polynomial. + /// + /// Polynomial + /// Resulting Polynomial + public static Polynomial operator -(Polynomial a) + { + return Negate(a); + } + /// /// multiplies a Polynomial by a Polynomial using convolution [ASINCO.libs.subfun.conv(a.Coeffs, b.Coeffs)] /// - /// left Polynomial - /// right Polynomial + /// Left polynomial + /// Right polynomial /// resulting Polynomial public static Polynomial operator *(Polynomial a, Polynomial b) { @@ -219,15 +307,14 @@ namespace MathNet.Numerics //ret_p.Trim(); return result; - } /// /// multiplies a Polynomial by a scalar /// - /// left Polynomial - /// scalar value - /// resulting Polynomial + /// Polynomial + /// Scalar value + /// Resulting Polynomial public static Polynomial operator *(Polynomial a, double k) { var aa = a.Clone() as Polynomial; @@ -238,40 +325,12 @@ namespace MathNet.Numerics return aa; } - /// - /// adds a scalar to a Polynomial (to the x^0 element) - /// - /// left Polynomial - /// scalar value - /// resulting Polynomial - public static Polynomial operator +(Polynomial a, double k) - { - var aa = a.Clone() as Polynomial; - - aa.Coefficients[0] += k; - return aa; - } - - /// - /// substracs a scalar from a Polynomial (from the x^0 element) - /// - /// left Polynomial - /// scalar value - /// resulting Polynomial - public static Polynomial operator -(Polynomial a, double k) - { - var aa = a.Clone() as Polynomial; - - a.Coefficients[0] -= k; - return aa; - } - /// /// divide Polynomial by scalar value /// - /// left Polynomial - /// scalar value - /// resulting Polynomial + /// Polynomial + /// Scalar value + /// Resulting Polynomial public static Polynomial operator /(Polynomial a, double k) { var aa = a.Clone() as Polynomial; @@ -282,28 +341,6 @@ namespace MathNet.Numerics return aa; } - /// - /// Addition of two Polynomials (piecewise) - /// - /// left Polynomial - /// right Polynomial - /// resulting Polynomial - public static Polynomial operator +(Polynomial a, Polynomial b) - { - return Add(a, b); - } - - /// - /// Subtraction of two Polynomials (piecewise) - /// - /// left Polynomial - /// right Polynomial - /// resulting Polynomial - public static Polynomial operator -(Polynomial a, Polynomial b) - { - return Subtract(a, b); - } - /// /// Calculates the complex roots of the Polynomial by eigenvalue decomposition /// @@ -365,61 +402,70 @@ namespace MathNet.Numerics } /// - /// Point-wise division of two Polynomials + /// Addition of two Polynomials (point-wise). /// /// Left Polynomial /// Right Polynomial /// Resulting Polynomial - public static Polynomial PointwiseDivide(Polynomial a, Polynomial b) + public static Polynomial Add(Polynomial a, Polynomial b) { var ac = a.Coefficients; var bc = b.Coefficients; - var degree = a.Degree; + var degree = Math.Max(a.Degree, b.Degree); var result = new double[degree + 1]; var commonLength = Math.Min(Math.Min(ac.Length, bc.Length), result.Length); for (int i = 0; i < commonLength; i++) { - result[i] = ac[i] / bc[i]; + result[i] = ac[i] + bc[i]; } - for (int i = commonLength; i < result.Length; i++) + int acLength = Math.Min(ac.Length, result.Length); + for (int i = commonLength; i < acLength; i++) { - result[i] = ac[i] / 0.0; + // no need to add since only one of both applies + result[i] = ac[i]; + } + + int bcLength = Math.Min(bc.Length, result.Length); + for (int i = commonLength; i < bcLength; i++) + { + // no need to add since only one of both applies + result[i] = bc[i]; } return new Polynomial(result); } /// - /// Point-wise multiplication of two Polynomials + /// Addition of a polynomial and a scalar. /// - /// Left Polynomial - /// Right Polynomial - /// Resulting Polynomial - public static Polynomial PointwiseMultiply(Polynomial a, Polynomial b) + public static Polynomial Add(Polynomial a, double b) { var ac = a.Coefficients; - var bc = b.Coefficients; - var degree = Math.Min(a.Degree, b.Degree); + var degree = Math.Max(a.Degree, 0); var result = new double[degree + 1]; - for (int i = 0; i < result.Length; i++) + + var commonLength = Math.Min(ac.Length, result.Length); + for (int i = 0; i < commonLength; i++) { - result[i] = ac[i] * bc[i]; + result[i] = ac[i]; } + result[0] += b; + return new Polynomial(result); } /// - /// Addition of two Polynomials (point-wise). + /// Subtraction of two Polynomials (point-wise). /// /// Left Polynomial /// Right Polynomial /// Resulting Polynomial - public static Polynomial Add(Polynomial a, Polynomial b) + public static Polynomial Subtract(Polynomial a, Polynomial b) { var ac = a.Coefficients; var bc = b.Coefficients; @@ -430,7 +476,7 @@ namespace MathNet.Numerics var commonLength = Math.Min(Math.Min(ac.Length, bc.Length), result.Length); for (int i = 0; i < commonLength; i++) { - result[i] = ac[i] + bc[i]; + result[i] = ac[i] - bc[i]; } int acLength = Math.Min(ac.Length, result.Length); @@ -444,44 +490,103 @@ namespace MathNet.Numerics for (int i = commonLength; i < bcLength; i++) { // no need to add since only one of both applies - result[i] = bc[i]; + result[i] = -bc[i]; } return new Polynomial(result); } /// - /// Subtraction of two Polynomials (point-wise). + /// Addition of a scalar from a polynomial. + /// + public static Polynomial Subtract(Polynomial a, double b) + { + return Add(a, -b); + } + + /// + /// Addition of a polynomial from a scalar. + /// + public static Polynomial Subtract(double b, Polynomial a) + { + var ac = a.Coefficients; + + var degree = Math.Max(a.Degree, 0); + var result = new double[degree + 1]; + + var commonLength = Math.Min(ac.Length, result.Length); + for (int i = 0; i < commonLength; i++) + { + result[i] = -ac[i]; + } + + result[0] += b; + + return new Polynomial(result); + } + + /// + /// Negation of a polynomial. + /// + public static Polynomial Negate(Polynomial a) + { + var ac = a.Coefficients; + + var degree = a.Degree; + var result = new double[degree + 1]; + + for (int i = 0; i < result.Length; i++) + { + result[i] = -ac[i]; + } + + return new Polynomial(result); + } + + /// + /// Point-wise division of two Polynomials /// /// Left Polynomial /// Right Polynomial /// Resulting Polynomial - public static Polynomial Subtract(Polynomial a, Polynomial b) + public static Polynomial PointwiseDivide(Polynomial a, Polynomial b) { var ac = a.Coefficients; var bc = b.Coefficients; - var degree = Math.Max(a.Degree, b.Degree); + var degree = a.Degree; var result = new double[degree + 1]; var commonLength = Math.Min(Math.Min(ac.Length, bc.Length), result.Length); for (int i = 0; i < commonLength; i++) { - result[i] = ac[i] - bc[i]; + result[i] = ac[i] / bc[i]; } - int acLength = Math.Min(ac.Length, result.Length); - for (int i = commonLength; i < acLength; i++) + for (int i = commonLength; i < result.Length; i++) { - // no need to add since only one of both applies - result[i] = ac[i]; + result[i] = ac[i] / 0.0; } - int bcLength = Math.Min(bc.Length, result.Length); - for (int i = commonLength; i < bcLength; i++) + return new Polynomial(result); + } + + /// + /// Point-wise multiplication of two Polynomials + /// + /// Left Polynomial + /// Right Polynomial + /// Resulting Polynomial + public static Polynomial PointwiseMultiply(Polynomial a, Polynomial b) + { + var ac = a.Coefficients; + var bc = b.Coefficients; + + var degree = Math.Min(a.Degree, b.Degree); + var result = new double[degree + 1]; + for (int i = 0; i < result.Length; i++) { - // no need to add since only one of both applies - result[i] = -bc[i]; + result[i] = ac[i] * bc[i]; } return new Polynomial(result);