From 8bfb3535eff8efdf191733287bc1132b94112581 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sun, 14 Oct 2018 19:22:57 +0200 Subject: [PATCH] Polynomial: rename Degree to CoefficientCount and add new Degree that matches the mathematical definition --- src/Numerics.Tests/PolynomialTests.cs | 46 ++++++---------- src/Numerics/Polynomial.cs | 76 +++++++++++++++++---------- 2 files changed, 63 insertions(+), 59 deletions(-) diff --git a/src/Numerics.Tests/PolynomialTests.cs b/src/Numerics.Tests/PolynomialTests.cs index 9b96f3be..53c02817 100644 --- a/src/Numerics.Tests/PolynomialTests.cs +++ b/src/Numerics.Tests/PolynomialTests.cs @@ -29,12 +29,8 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Numerics; -using MathNet.Numerics; -using MathNet.Numerics.LinearRegression; -using MathNet.Numerics.Statistics; using NUnit.Framework; namespace MathNet.Numerics.UnitTests @@ -46,7 +42,6 @@ namespace MathNet.Numerics.UnitTests [TestFixture, Category("Calculus")] public class PolynomialTests { - [TestCase(new double[] { 5, 4, 3, 0, 2 }, "5 + 4x^1 + 3x^2 + 0x^3 + 2x^4")] [TestCase(new double[0], "")] [TestCase(new double[] { 0, 4, 3, 0, 0 }, "0 + 4x^1 + 3x^2 + 0x^3 + 0x^4")] @@ -71,13 +66,12 @@ namespace MathNet.Numerics.UnitTests } else { - Assert.AreEqual(expected.Length, p_res.Degree, "length mismatch"); - for (int k = 0; k < p_res.Degree; k++) + Assert.AreEqual(expected.Length, p_res.CoefficientCount, "length mismatch"); + for (int k = 0; k < p_res.CoefficientCount; k++) { Assert.AreEqual(expected[k], p_res.Coeffs[k], "idx: " + k + " mismatch"); } } - } [TestCase(new double[] { 5, 4, 3, 0, 2 }, new double[] { 0, 5.0/1.0, 4.0/2.0, 3.0/3.0, 0.0/4.0, 2.0/5.0 })] @@ -95,8 +89,8 @@ namespace MathNet.Numerics.UnitTests } else { - Assert.AreEqual(expected.Length, p_res.Degree, "length mismatch"); - for (int k = 0; k < p_res.Degree; k++) + Assert.AreEqual(expected.Length, p_res.CoefficientCount, "length mismatch"); + for (int k = 0; k < p_res.CoefficientCount; k++) { Assert.AreEqual(expected[k], p_res.Coeffs[k], "idx: " + k + " mismatch"); } @@ -131,8 +125,8 @@ namespace MathNet.Numerics.UnitTests p_res.Trim(); p_tar.Trim(); - Assert.AreEqual(p_tar.Degree, p_res.Degree, "length mismatch"); - for (int k = 0; k < p_res.Degree; k++) + Assert.AreEqual(p_tar.CoefficientCount, p_res.CoefficientCount, "length mismatch"); + for (int k = 0; k < p_res.CoefficientCount; k++) { Assert.AreEqual(p_tar.Coeffs[k], p_res.Coeffs[k], msg); } @@ -168,8 +162,8 @@ namespace MathNet.Numerics.UnitTests p_res.Trim(); p_tar.Trim(); - Assert.AreEqual(p_tar.Degree, p_res.Degree, "length mismatch"); - for (int k = 0; k < p_res.Degree; k++) + Assert.AreEqual(p_tar.CoefficientCount, p_res.CoefficientCount, "length mismatch"); + for (int k = 0; k < p_res.CoefficientCount; k++) { Assert.AreEqual(p_tar.Coeffs[k], p_res.Coeffs[k], msg); } @@ -204,8 +198,8 @@ namespace MathNet.Numerics.UnitTests p_res.Trim(); p_tar.Trim(); - Assert.AreEqual(p_tar.Degree, p_res.Degree, "length mismatch"); - for (int k = 0; k < p_res.Degree; k++) + Assert.AreEqual(p_tar.CoefficientCount, p_res.CoefficientCount, "length mismatch"); + for (int k = 0; k < p_res.CoefficientCount; k++) { Assert.AreEqual(p_tar.Coeffs[k], p_res.Coeffs[k], msg); } @@ -227,15 +221,6 @@ namespace MathNet.Numerics.UnitTests } - public void DivideLongTestScalar(Tuple inVals, Tuple expectedVals) - { - var p1 = new Polynomial(1.0d); - var p2 = new Polynomial(new double[0]); - var tpl = Polynomial.DivideLong(p1, p2); - - - } - [Test] public void DivideLongTestWrongInputs() { @@ -268,7 +253,6 @@ namespace MathNet.Numerics.UnitTests [Test] public void DivideLongTest() { - var p11 = new Polynomial(2.0d); var p21 = new Polynomial(2.0d); var tpl1 = Polynomial.DivideLong(p11, p21); @@ -353,7 +337,7 @@ namespace MathNet.Numerics.UnitTests var e = eIn.OrderBy(v => v.Real).ToArray(); var r = r0.OrderBy(v => v.Real).ToArray(); - + Assert.IsNotNull(r); Assert.AreEqual(e.Length, r.Length, "length mismatch"); for (int k = 0; k < r.Length; k++) @@ -375,8 +359,8 @@ namespace MathNet.Numerics.UnitTests private void testEqual(double[] p_tar, Polynomial p_res, string msg = null) { - Assert.AreEqual(p_tar.Length, p_res.Degree, "length mismatch"); - for (int k = 0; k < p_res.Degree; k++) + Assert.AreEqual(p_tar.Length, p_res.CoefficientCount, "length mismatch"); + for (int k = 0; k < p_res.CoefficientCount; k++) { Assert.AreEqual(p_tar[k], p_res.Coeffs[k], msg); } @@ -384,8 +368,8 @@ namespace MathNet.Numerics.UnitTests } private void testEqual(Polynomial p_tar, Polynomial p_res, string msg = null) { - Assert.AreEqual(p_tar.Degree, p_res.Degree, "length mismatch"); - for (int k = 0; k < p_res.Degree; k++) + Assert.AreEqual(p_tar.CoefficientCount, p_res.CoefficientCount, "length mismatch"); + for (int k = 0; k < p_res.CoefficientCount; k++) { Assert.AreEqual(p_tar.Coeffs[k], p_res.Coeffs[k], msg); } diff --git a/src/Numerics/Polynomial.cs b/src/Numerics/Polynomial.cs index 64a57887..9ded9cea 100644 --- a/src/Numerics/Polynomial.cs +++ b/src/Numerics/Polynomial.cs @@ -1,21 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Numerics; -using MathNet.Numerics; using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra.Double; -using MathNet.Numerics.Statistics; -using MathNet.Numerics.IntegralTransforms; using MathNet.Numerics.LinearRegression; using MathNet.Numerics.LinearAlgebra.Factorization; namespace MathNet.Numerics { /// - /// a class handling REAL VALUED Polynomials, complex coefficients can not be handled (yet) + /// A single-variable polynomial with real-valued coefficients. /// public class Polynomial { @@ -32,7 +27,7 @@ namespace MathNet.Numerics /// /// Length of Polynomial (max element + 1) e.G x^5 highest element, will give Length = 6 /// - public int Degree + public int CoefficientCount { get { @@ -40,6 +35,31 @@ namespace MathNet.Numerics } } + /// + /// Degree of the polynomial, i.e. the largest monomial exponent. For example, the degree of x^2+x^5 is 5. + /// The null-polynomial returns degree -1 because the correct degree, negative infinity, cannot be represented by integers. + /// + public int Degree + { + get + { + if (Coeffs == null) + { + return -1; + } + + for (int i = Coeffs.Length - 1; i >= 0; i--) + { + if (Coeffs[i] != 0.0) + { + return i; + } + } + + return -1; + } + } + /// /// constructor setting a Polynomial of size n containing only zeros /// @@ -96,13 +116,13 @@ namespace MathNet.Numerics /// public void Trim() { - if (Degree == 1) + if (CoefficientCount == 1) return; - int i = Degree - 1; + int i = CoefficientCount - 1; while (i >= 0 && Coeffs[i] == 0.0) i--; - + if (i < 0) Coeffs = new double[1] { 0.0 }; else if (i == 0) @@ -114,7 +134,7 @@ namespace MathNet.Numerics Coeffs = hold; } } - + #region Data Interaction @@ -155,7 +175,7 @@ namespace MathNet.Numerics #region diff/int public Polynomial Differentiate() { - + if (Coeffs.Length == 0) { return null; @@ -224,7 +244,7 @@ namespace MathNet.Numerics public static Polynomial operator *( Polynomial a, double k) { var aa = a.Clone() as Polynomial; - + for (int ii = 0; ii < aa.Coeffs.Length; ii++) aa.Coeffs[ii] *= k; @@ -269,7 +289,7 @@ namespace MathNet.Numerics public static Polynomial operator /( Polynomial a, double k) { var aa = a.Clone() as Polynomial; - + for (int ii = 0; ii < aa.Coeffs.Length; ii++) aa.Coeffs[ii] /= k; @@ -297,7 +317,7 @@ namespace MathNet.Numerics { return Substract(a, b); } - + /// /// Calculates the complex roots of the Polynomial by eigenvalue decomposition /// @@ -418,10 +438,10 @@ namespace MathNet.Numerics var aa = a.Clone() as Polynomial; var bb = b.Clone() as Polynomial; - if (aa.Degree != bb.Degree) + if (aa.CoefficientCount != bb.CoefficientCount) mkSameLength(ref aa, ref bb); - int n = aa.Degree; + int n = aa.CoefficientCount; double[] res = new double[n]; @@ -444,10 +464,10 @@ namespace MathNet.Numerics var aa = a.Clone() as Polynomial; var bb = b.Clone() as Polynomial; - if (aa.Degree != bb.Degree) + if (aa.CoefficientCount != bb.CoefficientCount) mkSameLength(ref aa, ref bb); - int n = aa.Degree; + int n = aa.CoefficientCount; double[] res = new double[n]; @@ -472,14 +492,14 @@ namespace MathNet.Numerics if (b == null) throw new ArgumentNullException("b"); - if (a.Degree <= 0) + if (a.CoefficientCount <= 0) throw new ArgumentOutOfRangeException("a Degree must be greater than zero"); - if (b.Degree <= 0) + if (b.CoefficientCount <= 0) throw new ArgumentOutOfRangeException("b Degree must be greater than zero"); - if (b.Coeffs[b.Degree-1] == 0) + if (b.Coeffs[b.CoefficientCount-1] == 0) throw new DivideByZeroException("b polynomial ends with zero"); - + var c1 = a.Coeffs.ToArray(); var c2 = b.Coeffs.ToArray(); @@ -497,7 +517,7 @@ namespace MathNet.Numerics quo[i] = c1[i] / fact; rem = new double[] { 0 }; } - else if(n1 < n2) // denominator degree higher than nominator degree + else if(n1 < n2) // denominator degree higher than nominator degree { // quotient always be 0 and return c1 as remainder quo = new double[] { 0 }; @@ -534,7 +554,7 @@ namespace MathNet.Numerics for (int k = 0; k < j1; k++) rem[k] = c1[k]; - + } if (rem == null) @@ -547,7 +567,7 @@ namespace MathNet.Numerics // output mapping var pQuo = new Polynomial(quo); var pRem = new Polynomial(rem); - + pRem.Trim(); pQuo.Trim(); return new Tuple(pQuo, pRem); @@ -628,7 +648,7 @@ namespace MathNet.Numerics #region Interfacing /// - /// This method returns the coefficcients of the Polynomial as an array the "IsFlipped" property, + /// This method returns the coefficcients of the Polynomial as an array the "IsFlipped" property, /// which is set during construction is taken into account automatically. /// /// the coefficcients of the Polynomial as an array @@ -666,7 +686,7 @@ namespace MathNet.Numerics } /// - /// (full) convolution of two arrays + /// (full) convolution of two arrays /// /// left vector /// right vector