Implement finding extrema for cubic splines
I wanted to find extrema for a spline and had to implement it by myself, using the CubicSpline.cs of MathNet.Numerics. Unfortunately the Class is constructes thus, that I could not access the spline parameters which would have allowed my to simply write an extension method.
I propose the following addition to the class "CubicSpline":
public enum eExtremePointType
{
Minimum, Maximum
}
public class cExtremePointResult
{
public eExtremePointType Type { get; private set; }
public double x { get; private set; }
public double y [get;private set;}
public cExtremePointResult(double in_x, double in_y, eExtremePointType in_type)
{
x=inx;
y=iny;
Type=in_type;
}
}
/// <summary>
/// Calculate all absolute maxima and minima of the spline between its support points
/// </summary>
/// <returns>IEnumerable of extreme points ordered ascending by x</returns>
public IEnumerable<cExtremePointResult> GetExtrema()
{
List<cExtremePointResult> extrema = new List<cExtremePointResult>(); // Initialize result list
for (int i = 0; i < _x.Length - 1; i++) // For every interval between two support points
{
foreach (double x in PQFormula(2 * _c2[i] / (3 * _c3[i]), _c1[i] / (3 * _c3[i]))) // Get the zeroes of the first derivate of the cubic function between those points => first condition for extreme points
{
Debug.Print(x.ToString()+"|"+(x+_x[i]).ToString());
if (!double.IsNaN(x)) // Filter out invalid zeroes (linke division by 0 or root of negative values in pq-formula
{
if (x+_x[i] >= _x[i] && x+_x[i] <= _x[i + 1]) // check wether zero is in current interval between support points
{
// Add point to list of extrema. Evaluating the second derivate gives the information wether it is a maximum or a minimum we have found
extrema.Add(new cExtremePointResult(x + _x[i], Interpolate(x + _x[i]), Differentiate2(x + _x[i]) > 0 ? eExtremePointType.Minimum : eExtremePointType.Maximum));
}
}
}
}
return extrema.OrderBy(x => x.Point.X); // Order results ascending by x
}
/// <summary>
/// Solve qudaratic function with pq formula: https://en.wikipedia.org/wiki/Quadratic_equation#Reduced_quadratic_equation
/// </summary>
/// <param name="p">Parameter p</param>
/// <param name="q">Parameter q</param>
/// <returns>Enumerable of zeroes of the quadratic function</returns>
IEnumerable<double> PQFormula(double p, double q)
{
// We want to return distinct to prevent us having one point twice (think zero of x²)
return (new List<double>() { -p / 2.0 + Math.Sqrt((p / 2.0) * (p / 2.0) - q), -p / 2.0 - Math.Sqrt((p / 2.0) * (p / 2.0) - q) }).Distinct();
}
This code works like a charm for me and I would appreciate if it could be integrated in the CubicSpline class to prevent me having to have two Spline classes basically doing the same except the extrema handling