From 479d200b2a38b09d03635e7d13c998e9d3cdec1c Mon Sep 17 00:00:00 2001 From: Hylke Faas Date: Mon, 13 Mar 2023 13:50:52 +0100 Subject: [PATCH 1/2] Introduce a maxDeltaT to check if referencing points are within acceptable range. --- .../InterpolationTests/LinearSplineTest.cs | 26 +++++++++++++++++++ src/Numerics/Interpolation/LinearSpline.cs | 23 +++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/Numerics.Tests/InterpolationTests/LinearSplineTest.cs b/src/Numerics.Tests/InterpolationTests/LinearSplineTest.cs index 79980ee31..d68b92931 100644 --- a/src/Numerics.Tests/InterpolationTests/LinearSplineTest.cs +++ b/src/Numerics.Tests/InterpolationTests/LinearSplineTest.cs @@ -138,5 +138,31 @@ public void FewSamples() Assert.That(() => LinearSpline.Interpolate(new double[1], new double[1]), Throws.ArgumentException); Assert.That(LinearSpline.Interpolate(new[] { 1.0, 2.0 }, new[] { 2.0, 2.0 }).Interpolate(1.0), Is.EqualTo(2.0)); } + + [TestCase(-2.4, .6, 1.5, 1e-15)] + [TestCase(-0.9, 1.7, 1.0, 1e-15)] + [TestCase(-0.5, .5, 1.0, 1e-15)] + [TestCase(-0.1, -.7, 1.0, 1e-15)] + [TestCase(0.1, -.9, 1.0, 1e-15)] + [TestCase(0.4, -.6, 1.0, 1e-15)] + [TestCase(1.2, .2, 1.0, 1e-15)] + [TestCase(10.0, 9.0, double.MaxValue, 1e-15)] + [TestCase(-10.0, -7.0, double.MaxValue, 1e-15)] + public void DeltaTCommonPoints(double t, double x, double maxDeltaT, double maxAbsoluteError) + { + LinearSpline ip = LinearSpline.Interpolate(_t, _y); + Assert.AreEqual(x, ip.Interpolate(t, maxDeltaT), maxAbsoluteError, "Interpolation at {0}", t); + } + + [TestCase(0.1, -.9, 0.2)] + [TestCase(0.4, -.6, .2)] + [TestCase(1.2, .2, .2)] + [TestCase(10.0, 9.0, .2)] + [TestCase(-10.0, -7.0, .2)] + public void DeltaTPointTooNarrow(double t, double x, double maxDeltaT) + { + LinearSpline ip = LinearSpline.Interpolate(_t, _y); + Assert.Throws(() => ip.Interpolate(t, maxDeltaT)); + } } } diff --git a/src/Numerics/Interpolation/LinearSpline.cs b/src/Numerics/Interpolation/LinearSpline.cs index 0f192c3e3..66e773893 100644 --- a/src/Numerics/Interpolation/LinearSpline.cs +++ b/src/Numerics/Interpolation/LinearSpline.cs @@ -129,9 +129,30 @@ public static LinearSpline Interpolate(IEnumerable x, IEnumerablePoint t to interpolate at. /// Interpolated value x(t). public double Interpolate(double t) + { + return Interpolate(t, double.MaxValue); + } + + /// + /// Interpolate at point t. + /// + /// Point t to interpolate at. + /// Maximum allowed delta between point 't' and reference points. + /// Interpolated value x(t). + /// Thrown when distance from xn or xn+1 to 't' is exceeding . + public double Interpolate(double t, double maxDeltaT) { int k = LeftSegmentIndex(t); - return _c0[k] + (t - _x[k])*_c1[k]; + + if (Math.Abs(t - _x[k]) > maxDeltaT) + { + throw new InterpolatingDistanceException("Lower bound point exceeds maxDetlaT."); + } + else if (Math.Abs(_x[k + 1] - t) > maxDeltaT) + { + throw new InterpolatingDistanceException("Upper bound point exceeds maxDetlaT."); + } + return _c0[k] + (t - _x[k]) * _c1[k]; } /// From 5097a9560973d93cc20fa4672c27e5a94591c3e7 Mon Sep 17 00:00:00 2001 From: Hylke Faas Date: Mon, 13 Mar 2023 15:14:09 +0100 Subject: [PATCH 2/2] Missed the added Exception --- src/Numerics/Exceptions.cs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Numerics/Exceptions.cs b/src/Numerics/Exceptions.cs index 3745b9c5f..6a2a77d5b 100644 --- a/src/Numerics/Exceptions.cs +++ b/src/Numerics/Exceptions.cs @@ -154,4 +154,32 @@ protected SingularUMatrixException(System.Runtime.Serialization.SerializationInf { } } + + /// + /// Distance between point 't' and reference points is too large (can lead to inaccurate interpolation). + /// + [Serializable] + public class InterpolatingDistanceException : Exception + + { + public InterpolatingDistanceException() + : base("Distace from 't' to the two closest points exceeds MaxDeltaT.") + { + } + + public InterpolatingDistanceException(string message) + : base(message) + { + } + + public InterpolatingDistanceException(string message, Exception innerException) + : base(message, innerException) + { + } + + protected InterpolatingDistanceException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + : base(info, context) + { + } + } }