Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion src/Numerics/FindRoots.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>

using System;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Complex;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.RootFinding;
using System;
using System.Linq;
using Complex = System.Numerics.Complex;

namespace MathNet.Numerics
Expand Down Expand Up @@ -118,6 +122,39 @@ public static Complex[] Polynomial(double[] coefficients)
return new Polynomial(coefficients).Roots();
}

/// <summary>
/// Find all roots of a polynomial with complex coefficients by calculating the characteristic polynomial of the companion matrix
/// </summary>
/// <param name="coefficients">The coefficients of the polynomial in ascending order, e.g. new Complex[] {new (5, 0), new (0, 2) new (2,3)} = "5 + 2i x^1 + (2 + 3i) x^2"</param>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new (0, 2) new (2,3) -> new (0, 2), new (2,3) (a comma is missing)

/// <returns>The roots of the polynomial</returns>

public static Complex[] Roots(Complex[] coefficients)
{
int n = coefficients.Length;
if (n < 2)
{
return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to return an empty array/list instead of null?

}

// Negate, and normalize (scale such that the polynomial becomes monic)
Complex aN = coefficients[n];
Complex[] p = new Complex[n];
for (int i = n - 1; i >= 0; i--)
{
p[i] = -coefficients[i] / aN;
}

DenseMatrix A0 = DenseMatrix.CreateDiagonal(n - 1, n - 1, 1.0);
DenseMatrix A = new DenseMatrix(n);

A.SetSubMatrix(1, 0, A0);
A.SetRow(0, p.Reverse().ToArray());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be the last column, based on this wiki article?
https://en.wikipedia.org/wiki/Companion_matrix

Unless you decide to set the submatrix from the second column and first row. Or maybe I am confused :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So to be entirely honest, I don't know the theory. This is based entirely on the existing .Roots() property in the Polynomial class, which uses Evd to approximate the roots when the polynomial is higher than degree 3, if I'm not mistaken. I monkeyed around with the complex version of the DenseMatrix class and found out everything still works.

I'll triple check that this is producing accurate roots, but it seemed to pass the unit test w/o issue.


Evd<Complex> eigen = A.Evd(Symmetricity.Asymmetric);

return eigen.EigenValues.ToArray();
}

/// <summary>
/// Find all roots of a polynomial by calculating the characteristic polynomial of the companion matrix
/// </summary>
Expand Down