diff --git a/src/Numerics.Tests/PolynomialTests.cs b/src/Numerics.Tests/PolynomialTests.cs
index 1385d26a..0c696f66 100644
--- a/src/Numerics.Tests/PolynomialTests.cs
+++ b/src/Numerics.Tests/PolynomialTests.cs
@@ -42,58 +42,57 @@ 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")]
+ [TestCase(new double[] { 5, 4, 3, 0, 2 }, "5 + 4x + 3x^2 + 2x^4")]
+ [TestCase(new double[0], "0")]
+ [TestCase(new double[] { 0, 4, 3, 0, 0 }, "4x + 3x^2")]
+ [TestCase(new double[] { 0, -4, 3 }, "-4x + 3x^2")]
+ [TestCase(new double[] { 0, -4, -3 }, "-4x - 3x^2")]
+ [TestCase(new double[] { 0, 4, -3 }, "4x - 3x^2")]
public void ToStringTest(double[] x, string expected)
{
var p = new Polynomial(x);
Assert.AreEqual(expected, p.ToString());
}
+ [TestCase(new double[] { 5, 4, 3, 0, 2 }, "2x^4 + 3x^2 + 4x + 5")]
+ [TestCase(new double[0], "0")]
+ [TestCase(new double[] { 0, 4, 3, 0, 0 }, "3x^2 + 4x")]
+ [TestCase(new double[] { 0, -4, 3 }, "3x^2 - 4x")]
+ [TestCase(new double[] { 0, -4, -3 }, "-3x^2 - 4x")]
+ [TestCase(new double[] { 0, 4, -3 }, "-3x^2 + 4x")]
+ public void ToStringTestReverse(double[] x, string expected)
+ {
+ var p = new Polynomial(x);
+ Assert.AreEqual(expected, p.ToString(highestFirst:true));
+ }
+
[TestCase(new double[] { 5, 4, 3, 0, 2 }, new double[] { 4*1, 3*2, 0*3, 2*4 })]
- [TestCase(new double[0], null)]
+ [TestCase(new double[0], new double[0])]
[TestCase(new double[] { 0, 4, 3, 0, 0 }, new double[] { 4*1, 3*2 })]
public void DifferentiateTest(double[] x, double[] expected)
{
var p = new Polynomial(x);
var p_res = p.Differentiate();
- if (expected == null)
- {
- Assert.IsNull(p_res);
- return;
- }
- else
+ Assert.AreEqual(expected.Length, p_res.Coefficients.Length, "length mismatch");
+ for (int k = 0; k < p_res.Coefficients.Length; k++)
{
- Assert.AreEqual(expected.Length, p_res.Coefficients.Length, "length mismatch");
- for (int k = 0; k < p_res.Coefficients.Length; k++)
- {
- Assert.AreEqual(expected[k], p_res.Coefficients[k], "idx: " + k + " mismatch");
- }
+ Assert.AreEqual(expected[k], p_res.Coefficients[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 })]
- [TestCase(new double[0], new double[1] { 0 })]
+ [TestCase(new double[0], new double[0])]
[TestCase(new double[] { 0, 1, 6, 8 }, new double[] {0, 0.0/1.0, 1.0/2.0, 6.0/3.0, 8.0/4.0})]
public void IntegrateTest(double[] x, double[] expected)
{
var p = new Polynomial(x);
var p_res = p.Integrate();
- if (expected == null)
- {
- Assert.IsNull(p_res);
- return;
- }
- else
+ Assert.AreEqual(expected.Length, p_res.Coefficients.Length, "length mismatch");
+ for (int k = 0; k < p_res.Coefficients.Length; k++)
{
- Assert.AreEqual(expected.Length, p_res.Coefficients.Length, "length mismatch");
- for (int k = 0; k < p_res.Coefficients.Length; k++)
- {
- Assert.AreEqual(expected[k], p_res.Coefficients[k], "idx: " + k + " mismatch");
- }
+ Assert.AreEqual(expected[k], p_res.Coefficients[k], "idx: " + k + " mismatch");
}
}
@@ -122,9 +121,6 @@ namespace MathNet.Numerics.UnitTests
var p_res = Polynomial.Add(p1, p2);
var p_tar = new Polynomial(tgt);
- p_res.Trim();
- p_tar.Trim();
-
Assert.AreEqual(p_tar.Coefficients.Length, p_res.Coefficients.Length, "length mismatch");
for (int k = 0; k < p_res.Coefficients.Length; k++)
{
@@ -159,9 +155,6 @@ namespace MathNet.Numerics.UnitTests
var p_res = Polynomial.Subtract(p1, p2);
var p_tar = new Polynomial(tgt);
- p_res.Trim();
- p_tar.Trim();
-
Assert.AreEqual(p_tar.Coefficients.Length, p_res.Coefficients.Length, "length mismatch");
for (int k = 0; k < p_res.Coefficients.Length; k++)
{
@@ -195,9 +188,6 @@ namespace MathNet.Numerics.UnitTests
var p_res = p1 * p2;
var p_tar = new Polynomial(tgt);
- p_res.Trim();
- p_tar.Trim();
-
Assert.AreEqual(p_tar.Coefficients.Length, p_res.Coefficients.Length, "length mismatch");
for (int k = 0; k < p_res.Coefficients.Length; k++)
{
@@ -208,15 +198,14 @@ namespace MathNet.Numerics.UnitTests
}
- [TestCase(new double[] { 5, 4, 0 }, "5 + 4x^1")]
+ [TestCase(new double[] { 5, 4, 0 }, "5 + 4x")]
[TestCase(new double[] { 0, 0, 0 }, "0")]
- [TestCase(new double[] { 5, 4, 3, 0, 2 }, "5 + 4x^1 + 3x^2 + 0x^3 + 2x^4")]
- [TestCase(new double[] { 0, 0, 8, 0, 0 }, "0 + 0x^1 + 8x^2")]
- [TestCase(new double[] { 0, 4, 3, 0, 0 }, "0 + 4x^1 + 3x^2")]
+ [TestCase(new double[] { 5, 4, 3, 0, 2 }, "5 + 4x + 3x^2 + 2x^4")]
+ [TestCase(new double[] { 0, 0, 8, 0, 0 }, "8x^2")]
+ [TestCase(new double[] { 0, 4, 3, 0, 0 }, "4x + 3x^2")]
public void TrimTest(double[] x, string expected)
{
var p = new Polynomial(x);
- p.Trim();
Assert.AreEqual(expected, p.ToString());
}
@@ -224,29 +213,29 @@ namespace MathNet.Numerics.UnitTests
[Test]
public void DivideLongTestWrongInputs()
{
- Assert.Throws(typeof(ArgumentOutOfRangeException), () =>
+ Assert.Throws(typeof(DivideByZeroException), () =>
{
var p1 = new Polynomial(1.0d);
var p2 = new Polynomial(new double[0]);
- var tpl = Polynomial.DivideRemainder(p1, p2);
+ GC.KeepAlive(Polynomial.DivideRemainder(p1, p2));
});
- Assert.Throws(typeof(ArgumentOutOfRangeException), () =>
+ Assert.DoesNotThrow(() =>
{
- var p1 = new Polynomial(1.0d);
- var p2 = new Polynomial(new double[0]);
- var tpl = Polynomial.DivideRemainder(p2, p1);
+ var p1 = new Polynomial(new double[0]);
+ var p2 = new Polynomial(1.0d);
+ GC.KeepAlive(Polynomial.DivideRemainder(p1, p2));
});
- Assert.Throws(typeof(ArgumentOutOfRangeException), () =>
+ Assert.Throws(typeof(DivideByZeroException), () =>
{
var p1 = new Polynomial(new double[0]);
var p2 = new Polynomial(new double[0]);
- var tpl = Polynomial.DivideRemainder(p2, p1);
+ GC.KeepAlive(Polynomial.DivideRemainder(p1, p2));
});
Assert.Throws(typeof(DivideByZeroException), () =>
{
var p1 = new Polynomial(1.0d);
var p2 = new Polynomial(0.0d);
- var tpl = Polynomial.DivideRemainder(p1, p2);
+ GC.KeepAlive(Polynomial.DivideRemainder(p1, p2));
});
}
@@ -257,13 +246,13 @@ namespace MathNet.Numerics.UnitTests
var p21 = new Polynomial(2.0d);
var tpl1 = Polynomial.DivideRemainder(p11, p21);
TestEqual(new double[] { 1.0 }, tpl1.Item1);
- TestEqual(new double[] { 0.0 }, tpl1.Item2);
+ TestEqual(new double[0], tpl1.Item2);
var p12 = new Polynomial(new double[] { 2.0d, 2.0d });
var p22 = new Polynomial(2.0d);
var tpl2 = Polynomial.DivideRemainder(p12, p22);
TestEqual(new double[] { 1.0, 1.0 }, tpl2.Item1);
- TestEqual(new double[] { 0.0 }, tpl2.Item2);
+ TestEqual(new double[0], tpl2.Item2);
for (int i = 0; i < 5; i++)
{
@@ -284,7 +273,6 @@ namespace MathNet.Numerics.UnitTests
var pquo = tpl3.Item1;
var prem = tpl3.Item2;
var pres = (pquo * pi) + prem;
- pres.Trim();
TestEqual(pres, tgt, msg);
}
diff --git a/src/Numerics/Polynomial.cs b/src/Numerics/Polynomial.cs
index 17d01237..d3f0952b 100644
--- a/src/Numerics/Polynomial.cs
+++ b/src/Numerics/Polynomial.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
+using System.Text;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearRegression;
@@ -22,7 +23,7 @@ namespace MathNet.Numerics
///
/// Only needed for the ToString method
///
- public string VarName = "x^";
+ public string VarName = "x";
///
/// Degree of the polynomial, i.e. the largest monomial exponent. For example, the degree of y=x^2+x^5 is 5, for y=3 it is 0.
@@ -194,37 +195,41 @@ namespace MathNet.Numerics
#region Calculus
public Polynomial Differentiate()
{
- if (Coefficients.Length == 0)
+ int n = Degree;
+ if (n < 0)
{
- return null;
+ return this;
+ }
+ if (n == 0)
+ {
+ // Zero
+ return new Polynomial();
}
- var t = Clone() as Polynomial;
- t.Trim();
- var cNew = new double[t.Coefficients.Length - 1];
- for (int i = 1; i < t.Coefficients.Length; i++)
+ var c = new double[n];
+ for (int i = 0; i < c.Length; i++)
{
- cNew[i - 1] = t.Coefficients[i] * i;
+ c[i] = Coefficients[i + 1] * (i + 1);
}
- var p = new Polynomial(cNew);
- p.Trim();
- return p;
+ return new Polynomial(c);
}
public Polynomial Integrate()
{
- var t = Clone() as Polynomial;
- t.Trim();
- var cNew = new double[t.Coefficients.Length + 1];
- for (int i = 1; i < cNew.Length; i++)
+ int n = Degree;
+ if (n < 0)
+ {
+ return this;
+ }
+
+ var c = new double[n + 2];
+ for (int i = 1; i < c.Length; i++)
{
- cNew[i] = t.Coefficients[i - 1] / i;
+ c[i] = Coefficients[i - 1] / i;
}
- var p = new Polynomial(cNew);
- p.Trim();
- return p;
+ return new Polynomial(c);
}
#endregion
@@ -496,19 +501,15 @@ namespace MathNet.Numerics
/// A tuple holding quotient in first and remainder in second
public static Tuple DivideRemainder(Polynomial a, Polynomial b)
{
- if (a == null)
- throw new ArgumentNullException(nameof(a));
- if (b == null)
- throw new ArgumentNullException(nameof(b));
-
- if (a.Coefficients.Length <= 0)
- throw new ArgumentOutOfRangeException("a Degree must be greater than zero");
- if (b.Coefficients.Length <= 0)
- throw new ArgumentOutOfRangeException("b Degree must be greater than zero");
-
- if (b.Coefficients[b.Coefficients.Length - 1] == 0)
+ if (b.Degree < 0)
throw new DivideByZeroException("b polynomial ends with zero");
+ if (a.Degree < 0)
+ {
+ // zero divided by non-zero is zero without remainder
+ return Tuple.Create(a, a);
+ }
+
var c1 = a.Coefficients.ToArray();
var c2 = b.Coefficients.ToArray();
@@ -581,8 +582,6 @@ namespace MathNet.Numerics
var pQuo = new Polynomial(quo);
var pRem = new Polynomial(rem);
- pRem.Trim();
- pQuo.Trim();
return new Tuple(pQuo, pRem);
}
#endregion
@@ -788,43 +787,113 @@ namespace MathNet.Numerics
/// string in displayed format
public string ToString(bool highestFirst)
{
- if (Coefficients == null)
+ if (Degree < 0)
{
- return "null";
- }
- if (Coefficients.Length == 0)
- {
- return "";
+ return "0";
}
- string result = "";
- if (!highestFirst)
+ var sb = new StringBuilder();
+ bool first = true;
+ if (highestFirst)
{
- for (int ii = 0; ii < Coefficients.Length; ii++)
+ for (int i = Coefficients.Length - 1; i >= 0; i--)
{
-
- if (ii == 0 && Coefficients.Length == 1)
- result += String.Format("{0}", Coefficients[ii], VarName, ii);
- else if (ii == 0)
- result += String.Format("{0} + ", Coefficients[ii], VarName, ii);
- else if (ii == Coefficients.Length - 1)
- result += String.Format("{0}{1}{2}", Coefficients[ii], VarName, ii);
+ double c = Coefficients[i];
+ if (c == 0.0)
+ {
+ continue;
+ }
+
+ if (first)
+ {
+ sb.Append(c);
+ if (i > 0)
+ {
+ sb.Append(VarName);
+ }
+ if (i > 1)
+ {
+ sb.Append("^");
+ sb.Append(i);
+ }
+
+ first = false;
+ }
else
- result += String.Format("{0}{1}{2} + ", Coefficients[ii], VarName, ii);
+ {
+ if (c < 0.0)
+ {
+ sb.Append(" - ");
+ sb.Append(-c);
+ }
+ else
+ {
+ sb.Append(" + ");
+ sb.Append(c);
+ }
+ if (i > 0)
+ {
+ sb.Append(VarName);
+ }
+ if (i > 1)
+ {
+ sb.Append("^");
+ sb.Append(i);
+ }
+ }
}
}
else
{
- for (int ii = Coefficients.Length - 1; ii >= 0; ii--)
+ for (int i = 0; i < Coefficients.Length; i++)
{
- if (ii == 0)
- result += Coefficients[ii].ToString();
+ double c = Coefficients[i];
+ if (c == 0.0)
+ {
+ continue;
+ }
+
+ if (first)
+ {
+ sb.Append(c);
+ if (i > 0)
+ {
+ sb.Append(VarName);
+ }
+ if (i > 1)
+ {
+ sb.Append("^");
+ sb.Append(i);
+ }
+
+ first = false;
+ }
else
- result += String.Format("{0}{1}{2} + ", Coefficients[ii], VarName, ii);
+ {
+ if (c < 0.0)
+ {
+ sb.Append(" - ");
+ sb.Append(-c);
+ }
+ else
+ {
+ sb.Append(" + ");
+ sb.Append(c);
+ }
+ if (i > 0)
+ {
+ sb.Append(VarName);
+ }
+ if (i > 1)
+ {
+ sb.Append("^");
+ sb.Append(i);
+ }
+ }
}
}
- return result;
+ return sb.ToString();
}
#endregion
}