Skip to content

Commit af511c1

Browse files
NetPro69cdrnet
authored andcommitted
Renamed GetHorizontalPoints to GetHorizontalDerivativeTValues and renamed and extended GetMaxPoint to GetMinMaxTValues. Aslo added unit tests for both functions.
1 parent fe178f0 commit af511c1

2 files changed

Lines changed: 75 additions & 28 deletions

File tree

src/Numerics.Tests/InterpolationTests/CubicSplineTest.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ public class CubicSplineTest
3939
{
4040
readonly double[] _t = { -2.0, -1.0, 0.0, 1.0, 2.0 };
4141
readonly double[] _y = { 1.0, 2.0, -1.0, 0.0, 1.0 };
42-
42+
//test data for min max values
43+
readonly double[] _x = { -4, -3, -2, -1, 0, 1, 2, 3, 4 };
44+
readonly double[] _z = { -7, 2, 5, 0, -3, -1, -4, 0, 6 };
45+
4346
/// <summary>
4447
/// Verifies that the interpolation matches the given value at all the provided sample points.
4548
/// </summary>
@@ -202,5 +205,37 @@ public void InterpolateAkimaSorted_MustBeThreadSafe_GitHub219([Values(8, 32, 256
202205

203206
CollectionAssert.DoesNotContain(yipol, Double.NaN);
204207
}
208+
209+
/// <summary>
210+
/// Tests that the cubic spline returns the correct t values where the derivative is 0
211+
/// </summary>
212+
[Test]
213+
public void NaturalSplineGetHorizontalDerivativeTValues()
214+
{
215+
CubicSpline it = CubicSpline.InterpolateBoundaries(_x, _z, SplineBoundaryCondition.SecondDerivative, -4.0, SplineBoundaryCondition.SecondDerivative, 4.0);
216+
var horizontalDerivatives = it.GetHorizontalDerivativeTValues();
217+
//readonly double[] _x = { -4, -3, -2, -1, 0, 1, 2, 3, 4 };
218+
//readonly double[] _z = { -7, 2, 5, 0, -3, -1, -4, 0, 6 };
219+
Assert.AreEqual(4, horizontalDerivatives.Length, "Incorrect number of points with derivative value equal to 0");
220+
Assert.IsTrue(horizontalDerivatives[0]>=-3 && horizontalDerivatives[0] <= -2,"Spline returns wrong t value: "+horizontalDerivatives[0]+" for first point");
221+
Assert.IsTrue(horizontalDerivatives[1] >= -1 && horizontalDerivatives[1] <= 0, "Spline returns wrong t value: " + horizontalDerivatives[1] + " for second point");
222+
Assert.IsTrue(horizontalDerivatives[2] >= 0 && horizontalDerivatives[2] <= 1, "Spline returns wrong t value: " + horizontalDerivatives[2] + " for third point");
223+
Assert.IsTrue(horizontalDerivatives[3] >= 2 && horizontalDerivatives[3] <= 3, "Spline returns wrong t value: " + horizontalDerivatives[3] + " for fourth point");
224+
Console.WriteLine("GetHorizontalDerivativeTValues checked out ok for cubic spline.");
225+
}
226+
227+
/// <summary>
228+
/// Tests that the min and max values for the natural spline are correct
229+
/// </summary>
230+
[Test]
231+
public void NaturalSplineGetMinMaxTvalues()
232+
{
233+
CubicSpline it = CubicSpline.InterpolateBoundaries(_x, _z, SplineBoundaryCondition.SecondDerivative, -4.0, SplineBoundaryCondition.SecondDerivative, 4.0);
234+
var minMax = it.GetMinMaxTValues();
235+
Assert.AreEqual(-4, minMax.Item1, "Spline returns wrong t value for global minimum");
236+
Assert.AreEqual(4, minMax.Item2, "Spline returns wrong t value for global maximum");
237+
Console.WriteLine("GetMinMaxTValues checked out ok for cubic spline.");
238+
239+
}
205240
}
206241
}

src/Numerics/Interpolation/CubicSpline.cs

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// <copyright file="CubicSpline.cs" company="Math.NET">
1+
// <copyright file="CubicSpline.cs" company="Math.NET">
22
// Math.NET Numerics, part of the Math.NET Project
33
// http://numerics.mathdotnet.com
44
// http://github.com/mathnet/mathnet-numerics
@@ -625,13 +625,13 @@ int LeftSegmentIndex(double t)
625625
}
626626

627627
/// <summary>
628-
/// Gets all the points (x values) where the derivative is 0
628+
/// Gets all the t values where the derivative is 0
629629
/// </summary>
630-
/// <returns>An array of X values where the derivative of the spline is 0</returns>
631-
public double[] GetHorizontalPoints()
630+
/// <returns>An array of t values (in the domain of teh function) where the derivative of the spline is 0</returns>
631+
public double[] GetHorizontalDerivativeTValues()
632632
{
633633
List<double> points = new List<double>();
634-
for (int index = 0; index < _x.Length-1; index++)
634+
for (int index = 0; index < _x.Length - 1; index++)
635635
{
636636
double a = 6 * _c3[index]; //derive ax^3 and multiply by 2
637637
double b = 2 * _c2[index]; //derive bx^2
@@ -640,58 +640,70 @@ public double[] GetHorizontalPoints()
640640
//first check if a is 0, if so its a linear function, this happens with quadratic condition
641641
if (a.AlmostEqual(0))
642642
{
643-
double x = _x[index] - c / b;
644-
//check if the result is in the domain
645-
if (_x[index] <= x && x <= _x[index + 1]) points.Add(x);
643+
double x = _x[index] - c / b;
644+
//check if the result is in the domain
645+
if (_x[index] <= x && x <= _x[index + 1]) points.Add(x);
646646
}
647647
else if (d.AlmostEqual(0))//its a quadratic with a single solution
648648
{
649-
double x = _x[index] - b / a;
650-
if (_x[index] <= x && x <= _x[index + 1]) points.Add(x);
649+
double x = _x[index] - b / a;
650+
if (_x[index] <= x && x <= _x[index + 1]) points.Add(x);
651651
}
652652
else if (d > 0)//only has a solution if d is greater than 0
653653
{
654-
d = (double)System.Math.Sqrt(d);
655-
//apply quadratic equation
656-
double x1 = _x[index]+ (-b + d) / a;
657-
double x2 = _x[index]+ (-b - d) / a;
658-
//Add any solution points that fall within the domain to the list
659-
if ((_x[index] <= x1) && (x1 <= _x[index + 1])) points.Add(x1);
660-
if ((_x[index] <= x2) && (x2 <= _x[index + 1])) points.Add(x2);
654+
d = (double)System.Math.Sqrt(d);
655+
//apply quadratic equation
656+
double x1 = _x[index] + (-b + d) / a;
657+
double x2 = _x[index] + (-b - d) / a;
658+
//Add any solution points that fall within the domain to the list
659+
if ((_x[index] <= x1) && (x1 <= _x[index + 1])) points.Add(x1);
660+
if ((_x[index] <= x2) && (x2 <= _x[index + 1])) points.Add(x2);
661661
}
662662
}
663663
return points.ToArray();
664664
}
665665

666666
/// <summary>
667-
/// Returns the maximum value for the spline within its domain.
667+
/// Returns the t values in the domain of the spline for which it takes the minimum and maximum value.
668668
/// </summary>
669-
/// <returns></returns>
670-
public double GetMaxPoint()
669+
/// <returns>A tuple containing the t value for which the spline is minimum in the first component and maximum in the second component </returns>
670+
public Tuple<double, double> GetMinMaxTValues()
671671
{
672672
double max = double.MinValue;
673-
double x=0;
673+
double min = double.MaxValue;
674+
double minT = 0;
675+
double maxT = 0;
674676
//go through the functions points to check if one of them has a higher value
675677
foreach (double p in _x)
676678
{
677679
double y = Interpolate(p);
678680
if (y > max)
679681
{
680-
max = y;
681-
x = p;
682+
max = y;
683+
maxT = p;
684+
}
685+
if (y < min)
686+
{
687+
min = y;
688+
minT = p;
682689
}
683690
}
684691
//go through the inflexion, local minimums and local maximums
685-
foreach (double p in GetHorizontalPoints())
692+
foreach (double p in GetHorizontalDerivativeTValues())
686693
{
687694
double y = Interpolate(p);
688695
if (y > max)
689696
{
690-
max = y;
691-
x = p;
697+
max = y;
698+
maxT = p;
699+
}
700+
if (y < min)
701+
{
702+
min = y;
703+
minT = p;
692704
}
693705
}
694-
return x;
706+
return new Tuple<double, double>(minT, maxT);
695707
}
696708
}
697709
}

0 commit comments

Comments
 (0)