diff --git a/src/Numerics/Interpolation/Algorithms/SplineInterpolation.cs b/src/Numerics/Interpolation/Algorithms/SplineInterpolation.cs
index 6b28cfcc..0d9084ee 100644
--- a/src/Numerics/Interpolation/Algorithms/SplineInterpolation.cs
+++ b/src/Numerics/Interpolation/Algorithms/SplineInterpolation.cs
@@ -111,7 +111,7 @@ namespace MathNet.Numerics.Interpolation.Algorithms
throw new ArgumentNullException("splineCoefficients");
}
- if (samplePoints.Count < 1)
+ if (samplePoints.Count < 2)
{
throw new ArgumentOutOfRangeException("samplePoints");
}
diff --git a/src/UnitTests/InterpolationTests/FunctionalHelpers.cs b/src/UnitTests/InterpolationTests/FunctionalHelpers.cs
new file mode 100644
index 00000000..e2d91552
--- /dev/null
+++ b/src/UnitTests/InterpolationTests/FunctionalHelpers.cs
@@ -0,0 +1,104 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://mathnet.opensourcedotnet.info
+//
+// Copyright (c) 2009 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using MathNet.Numerics.Interpolation;
+
+namespace MathNet.Numerics.UnitTests.InterpolationTests
+{
+ using System;
+
+ internal static class FunctionalHelpers
+ {
+ internal static Expression[] ApplySingleMap(
+ IList list,
+ int index,
+ Func replace)
+ {
+ var newList = new Expression[list.Count];
+ for (int i = 0; i < list.Count; i++)
+ {
+ newList[i] = (i == index) ? replace(list[i]) : list[i];
+ }
+
+ return newList;
+ }
+
+ internal static IEnumerable>> ApplySingleMapEachArgument(
+ this LambdaExpression lambda,
+ Func predicate,
+ Func replace)
+ {
+ var body = lambda.Body;
+ var arguments =
+ body is NewExpression
+ ? ((NewExpression)body).Arguments
+ : ((MethodCallExpression)body).Arguments;
+
+ for (int i = 0; i < arguments.Count; i++)
+ {
+ if (!predicate(arguments[i].Type))
+ {
+ continue;
+ }
+
+ var mappedArguments = ApplySingleMap(arguments, i, replace);
+
+ yield return Expression.Lambda>(
+ body is NewExpression
+ ? (Expression)Expression.New(
+ ((NewExpression)body).Constructor,
+ mappedArguments)
+ : (Expression)Expression.Call(
+ ((MethodCallExpression)body).Method,
+ mappedArguments));
+ }
+ }
+
+ internal static T ApplyReduceArgument(
+ this LambdaExpression lambda,
+ Func reduce,
+ T init)
+ {
+ var body = lambda.Body;
+ var arguments =
+ body is NewExpression
+ ? ((NewExpression)body).Arguments
+ : ((MethodCallExpression)body).Arguments;
+
+ T value = init;
+ foreach (var argument in arguments)
+ {
+ value = reduce(argument, value);
+ }
+
+ return value;
+ }
+ }
+}
diff --git a/src/UnitTests/InterpolationTests/InterpolationContract.cs b/src/UnitTests/InterpolationTests/InterpolationContract.cs
deleted file mode 100644
index 4dc559d2..00000000
--- a/src/UnitTests/InterpolationTests/InterpolationContract.cs
+++ /dev/null
@@ -1,378 +0,0 @@
-//
-// Math.NET Numerics, part of the Math.NET Project
-// http://mathnet.opensourcedotnet.info
-//
-// Copyright (c) 2009 Math.NET
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use,
-// copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following
-// conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-//
-
-namespace MathNet.Numerics.UnitTests.InterpolationTests
-{
- using System;
- using System.Collections.Generic;
- using Gallio.Framework.Assertions;
- using Interpolation;
- using MbUnit.Framework;
- using MbUnit.Framework.ContractVerifiers;
-
- internal class InterpolationContract : AbstractContract
- where TInterpolation : IInterpolation
- {
- public Func, IList, IInterpolation> Factory { get; set; }
- public int MinimumSampleCount { get; set; }
- public bool NonStandardParameters { get; set; }
- public bool LinearBehavior { get; set; }
- public bool PolynomialBehavior { get; set; }
- public bool RationalBehavior { get; set; }
-
- protected override IEnumerable GetContractVerificationTests()
- {
- // Infrastructure Tests
-
- yield return CreateFactoryReturnsCorrectTypeTest("FactoryReturnsCorrectType");
- yield return CreateConsistentCapabilityBehaviorTest("ConsistentCapabilityBehavior");
-
- yield return CreateInitChecksForNullTest("InitChecksForNull");
- yield return CreateInitChecksForMatchingCountTest("InitChecksForMatchingCount");
- yield return CreateInitChecksForMinimumCountTest("InitChecksForMinimumCount");
-
- if (!NonStandardParameters)
- {
- yield return CreateConstructorInitShortcutTest("ConstructorInitShortcut");
- }
-
- // Numerics Behavior Tests
-
- yield return CreateInterpolationMatchesNodePointsTest("InterpolationMatchesNodePoints");
-
- if (LinearBehavior && !NonStandardParameters)
- {
- yield return CreateLinearBehaviorTest("LinearBehavior");
- }
-
- if (PolynomialBehavior && !NonStandardParameters)
- {
- yield return CreatePolynomialBehaviorTest("PolynomialBehavior");
- }
-
- if (RationalBehavior && !NonStandardParameters)
- {
- yield return CreateRationalBehaviorTest("RationalBehavior");
- }
- }
-
- private Test CreateFactoryReturnsCorrectTypeTest(string name)
- {
- return new TestCase(name, () =>
- {
- double[] points, values;
- SampleFunctionEquidistant(t => 5 + 10 * t, -2.0, 8.0, MinimumSampleCount, out points, out values);
-
- var interpolation = Factory(points, values);
-
- AssertionHelper.Verify(() =>
- {
- // verify returned interpolation has the expected type
- if (interpolation.GetType() == typeof(TInterpolation))
- {
- return null;
- }
-
- return new AssertionFailureBuilder(
- "Expected the factory to return the correct type.")
- .AddRawLabeledValue("Interpolation Type", typeof(TInterpolation))
- .SetStackTrace(Context.GetStackTraceData())
- .ToAssertionFailure();
- });
- });
- }
-
- private Test CreateInitChecksForNullTest(string name)
- {
- return new TestCase(name, () =>
- {
- var points = new List { 1, 2, 3, 4, 5 };
- var values = new List { 10, 20, 30, 40, 50 };
-
- Assert.DoesNotThrow(() => Factory(points, values));
-
- Assert.Throws(typeof(ArgumentNullException), () => Factory(points, null));
- Assert.Throws(typeof(ArgumentNullException), () => Factory(null, values));
- Assert.Throws(typeof(ArgumentNullException), () => Factory(null, null));
- });
- }
-
- private Test CreateInitChecksForMatchingCountTest(string name)
- {
- return new TestCase(name, () =>
- {
- var points = new List { 1, 2, 3, 4, 5 };
- var valuesOk = new List { 10, 20, 30, 40, 50 };
- var valuesFail1 = new List { 10, 20, 30, 40 };
- var valuesFail2 = new List { 10, 20, 30, 40, 50, 60 };
-
- Assert.DoesNotThrow(() => Factory(points, valuesOk));
-
- Assert.Throws(typeof(ArgumentException), () => Factory(points, valuesFail1));
- Assert.Throws(typeof(ArgumentException), () => Factory(points, valuesFail2));
- });
- }
-
- private Test CreateInitChecksForMinimumCountTest(string name)
- {
- return new TestCase(name, () =>
- {
- double[] pointsOk, valuesOk;
- SampleFunctionEquidistant(t => 5 + 10 * t, -2.0, 8.0, MinimumSampleCount, out pointsOk, out valuesOk);
-
- Assert.DoesNotThrow(() => Factory(pointsOk, valuesOk));
-
- double[] pointsFail, valuesFail;
- SampleFunctionEquidistant(t => 5 + 10 * t, -2.0, 8.0, MinimumSampleCount - 1, out pointsFail, out valuesFail);
-
- Assert.Throws(typeof(ArgumentOutOfRangeException), () => Factory(pointsFail, valuesFail));
- });
- }
-
- private Test CreateConstructorInitShortcutTest(string name)
- {
- return new TestCase(name, () =>
- {
- var points = new List { 1, 2, 3, 4, 5 };
- var values = new List { 10, 20, 30, 40, 50 };
-
- var ctor = typeof(TInterpolation).GetConstructor(
- new[] { typeof (IList), typeof (IList) }
- );
-
- var interpolation = (IInterpolation)ctor.Invoke(
- new[] { points, values }
- );
-
- Assert.AreApproximatelyEqual(20, interpolation.Interpolate(2), 1e-12);
- });
- }
-
- private Test CreateConsistentCapabilityBehaviorTest(string name)
- {
- return new TestCase(name, () =>
- {
- double[] points, values;
- SampleFunctionEquidistant(t => 5 + 10 * t, -2.0, 8.0, MinimumSampleCount, out points, out values);
-
- var interpolation = Factory(points, values);
-
- // verify consistent differentiation capability
- if (interpolation.SupportsDifferentiation)
- {
- double a, b;
- Assert.DoesNotThrow(() => interpolation.Differentiate(1.2));
- Assert.DoesNotThrow(() => interpolation.Differentiate(1.2, out a, out b));
- }
- else
- {
- double a, b;
-
- Assert.Throws(
- typeof(NotSupportedException),
- () => interpolation.Differentiate(1.2));
-
- Assert.Throws(
- typeof(NotSupportedException),
- () => interpolation.Differentiate(1.2, out a, out b));
- }
-
- // verify consistent integration capability
- if (interpolation.SupportsIntegration)
- {
- Assert.DoesNotThrow(() => interpolation.Integrate(1.2));
- }
- else
- {
- Assert.Throws(
- typeof(NotSupportedException),
- () => interpolation.Integrate(1.2));
- }
- });
- }
-
- private Test CreateInterpolationMatchesNodePointsTest(string name)
- {
- return new TestCase(name, () =>
- {
- var points = new List { 1, 2, 2.3, 3, 8 };
- var values = new List { 50, 20, 30, 10, -20 };
- var interpolation = Factory(points, values);
-
- for (int i = 0; i < points.Count; i++)
- {
- Assert.AreApproximatelyEqual(
- values[i],
- interpolation.Interpolate(points[i]),
- 1e-12);
- }
- });
- }
-
- private Test CreateLinearBehaviorTest(string name)
- {
- return new TestCase(name, () =>
- {
- const double yOffset = 2.0;
- const double xOffset = 4.0;
- Random random = new Random();
-
- int[] orders = { MinimumSampleCount, MinimumSampleCount + 1, MinimumSampleCount + 5 };
-
- for (int k = 0; k < orders.Length; k++)
- {
- int order = orders[k];
-
- // build linear samples
- double[] points = new double[order];
- double[] values = new double[order];
- for (int i = 0; i < points.Length; i++)
- {
- points[i] = xOffset + i;
- values[i] = yOffset + i;
- }
-
- var interpolation = Factory(points, values);
-
- // build linear test vectors randomly between the sample points
- double[] testPoints = new double[order + 1];
- double[] testValues = new double[order + 1];
- if (order == 1)
- {
- testPoints[0] = xOffset - random.NextDouble();
- testPoints[1] = xOffset + random.NextDouble();
- testValues[0] = testValues[1] = yOffset;
- }
- else
- {
- for (int i = 0; i < testPoints.Length; i++)
- {
- double z = (i - 1) + random.NextDouble();
- testPoints[i] = xOffset + z;
- testValues[i] = yOffset + z;
- }
- }
-
- // verify interpolation with test samples
- for (int i = 0; i < testPoints.Length; i++)
- {
- Assert.AreApproximatelyEqual(
- testValues[i],
- interpolation.Interpolate(testPoints[i]),
- 1e-12);
- }
- }
- });
- }
-
- private Test CreatePolynomialBehaviorTest(string name)
- {
- return new TestCase(name, () =>
- {
- var points = new List { -2.0, -1.0, 0.0, 1.0, 2.0 };
- var values = new List { 1.0, 2.0, -1.0, 0.0, 1.0 };
- var interpolation = Factory(points, values);
-
- // Maple: "with(CurveFitting);"
- // Maple: "PolynomialInterpolation([[-2,1],[-1,2],[0,-1],[1,0],[2,1]], x);"
- Assert.AreApproximatelyEqual(-4.5968, interpolation.Interpolate(-2.4), 1e-6, "A -2.4");
- Assert.AreApproximatelyEqual(1.65395, interpolation.Interpolate(-0.9), 1e-6, "A -0.9");
- Assert.AreApproximatelyEqual(0.21875, interpolation.Interpolate(-0.5), 1e-6, "A -0.5");
- Assert.AreApproximatelyEqual(-0.84205, interpolation.Interpolate(-0.1), 1e-6, "A -0.1");
- Assert.AreApproximatelyEqual(-1.10805, interpolation.Interpolate(0.1), 1e-6, "A 0.1");
- Assert.AreApproximatelyEqual(-1.1248, interpolation.Interpolate(0.4), 1e-6, "A 0.4");
- Assert.AreApproximatelyEqual(0.5392, interpolation.Interpolate(1.2), 1e-6, "A 1.2");
- Assert.AreApproximatelyEqual(-4431.0, interpolation.Interpolate(10.0), 1e-6, "A 10.0");
- Assert.AreApproximatelyEqual(-5071.0, interpolation.Interpolate(-10.0), 1e-6, "A -10.0");
- });
- }
-
- private Test CreateRationalBehaviorTest(string name)
- {
- return new TestCase(name, () =>
- {
- double[] points, values;
- SampleFunctionEquidistant(t => 1 / (1 + (t * t)), -5.0, 5.0, 41, out points, out values);
- var interpolation = Factory(points, values);
-
- for (int i = 0; i < points.Length; i++)
- {
- Assert.AreApproximatelyEqual(
- values[i],
- interpolation.Interpolate(points[i]),
- 1e-12,
- "Match on knots");
- }
-
- double[] testPoints, testValues;
- SampleFunctionEquidistant(t => 1 / (1 + (t * t)), -5.0, 5.0, 81, out testPoints, out testValues);
-
- for (int i = 0; i < testPoints.Length; i++)
- {
- Assert.AreApproximatelyEqual(
- testValues[i],
- interpolation.Interpolate(testPoints[i]),
- 1e-5,
- "Match between knots");
- }
- });
- }
-
- private static void SampleFunctionEquidistant(
- Func f,
- double start,
- double stop,
- int samples,
- out double[] points,
- out double[] values)
- {
- points = new double[samples];
- values = new double[samples];
-
- if(samples == 0)
- {
- return;
- }
-
- if(samples == 1)
- {
- double t = points[0] = 0.5 * (start + stop);
- values[0] = f(t);
- return;
- }
-
- double step = (stop - start) / (samples - 1);
- for (int i = 0; i < points.Length; i++)
- {
- double t = start + (i * step);
- points[i] = t;
- values[i] = f(t);
- }
- }
- }
-}
diff --git a/src/UnitTests/InterpolationTests/InterpolationFunctionalContract.cs b/src/UnitTests/InterpolationTests/InterpolationFunctionalContract.cs
new file mode 100644
index 00000000..8f5a4e66
--- /dev/null
+++ b/src/UnitTests/InterpolationTests/InterpolationFunctionalContract.cs
@@ -0,0 +1,201 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://mathnet.opensourcedotnet.info
+//
+// Copyright (c) 2009 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.UnitTests.InterpolationTests
+{
+ using System;
+ using System.Collections.Generic;
+ using Interpolation;
+ using MbUnit.Framework;
+ using MbUnit.Framework.ContractVerifiers;
+
+ internal class InterpolationFunctionalContract : AbstractContract
+ where TInterpolation : IInterpolation
+ {
+ public Func, IList, IInterpolation> Factory { get; set; }
+ public int MinimumSampleCount { get; set; }
+ public bool LinearBehavior { get; set; }
+ public bool PolynomialBehavior { get; set; }
+ public bool RationalBehavior { get; set; }
+
+ protected override IEnumerable GetContractVerificationTests()
+ {
+ yield return CreateInterpolationMatchesNodePointsTest();
+
+ if (LinearBehavior)
+ {
+ yield return CreateLinearBehaviorTest();
+ }
+
+ if (PolynomialBehavior)
+ {
+ yield return CreatePolynomialBehaviorTest();
+ }
+
+ if (RationalBehavior)
+ {
+ yield return CreateRationalBehaviorTest();
+ }
+ }
+
+ private Test CreateInterpolationMatchesNodePointsTest()
+ {
+ return new TestCase(
+ "InterpolationMatchesNodePoints",
+ () =>
+ {
+ var points = new List { 1, 2, 2.3, 3, 8 };
+ var values = new List { 50, 20, 30, 10, -20 };
+ var interpolation = Factory(points, values);
+
+ for (int i = 0; i < points.Count; i++)
+ {
+ Assert.AreApproximatelyEqual(
+ values[i],
+ interpolation.Interpolate(points[i]),
+ 1e-12);
+ }
+ });
+ }
+
+ private Test CreateLinearBehaviorTest()
+ {
+ return new TestCase(
+ "LinearBehavior",
+ () =>
+ {
+ const double yOffset = 2.0;
+ const double xOffset = 4.0;
+ var random = new Random();
+
+ int[] orders = { MinimumSampleCount, MinimumSampleCount + 1, MinimumSampleCount + 5 };
+
+ for (int k = 0; k < orders.Length; k++)
+ {
+ int order = orders[k];
+
+ // build linear samples
+ var points = new double[order];
+ var values = new double[order];
+ for (int i = 0; i < points.Length; i++)
+ {
+ points[i] = xOffset + i;
+ values[i] = yOffset + i;
+ }
+
+ var interpolation = Factory(points, values);
+
+ // build linear test vectors randomly between the sample points
+ var testPoints = new double[order + 1];
+ var testValues = new double[order + 1];
+ if (order == 1)
+ {
+ testPoints[0] = xOffset - random.NextDouble();
+ testPoints[1] = xOffset + random.NextDouble();
+ testValues[0] = testValues[1] = yOffset;
+ }
+ else
+ {
+ for (int i = 0; i < testPoints.Length; i++)
+ {
+ double z = (i - 1) + random.NextDouble();
+ testPoints[i] = xOffset + z;
+ testValues[i] = yOffset + z;
+ }
+ }
+
+ // verify interpolation with test samples
+ for (int i = 0; i < testPoints.Length; i++)
+ {
+ Assert.AreApproximatelyEqual(
+ testValues[i],
+ interpolation.Interpolate(testPoints[i]),
+ 1e-12);
+ }
+ }
+ });
+ }
+
+ private Test CreatePolynomialBehaviorTest()
+ {
+ return new TestCase(
+ "PolynomialBehavior",
+ () =>
+ {
+ var points = new List { -2.0, -1.0, 0.0, 1.0, 2.0 };
+ var values = new List { 1.0, 2.0, -1.0, 0.0, 1.0 };
+ var interpolation = Factory(points, values);
+
+ // Maple: "with(CurveFitting);"
+ // Maple: "PolynomialInterpolation([[-2,1],[-1,2],[0,-1],[1,0],[2,1]], x);"
+ Assert.AreApproximatelyEqual(-4.5968, interpolation.Interpolate(-2.4), 1e-6, "A -2.4");
+ Assert.AreApproximatelyEqual(1.65395, interpolation.Interpolate(-0.9), 1e-6, "A -0.9");
+ Assert.AreApproximatelyEqual(0.21875, interpolation.Interpolate(-0.5), 1e-6, "A -0.5");
+ Assert.AreApproximatelyEqual(-0.84205, interpolation.Interpolate(-0.1), 1e-6, "A -0.1");
+ Assert.AreApproximatelyEqual(-1.10805, interpolation.Interpolate(0.1), 1e-6, "A 0.1");
+ Assert.AreApproximatelyEqual(-1.1248, interpolation.Interpolate(0.4), 1e-6, "A 0.4");
+ Assert.AreApproximatelyEqual(0.5392, interpolation.Interpolate(1.2), 1e-6, "A 1.2");
+ Assert.AreApproximatelyEqual(-4431.0, interpolation.Interpolate(10.0), 1e-6, "A 10.0");
+ Assert.AreApproximatelyEqual(-5071.0, interpolation.Interpolate(-10.0), 1e-6, "A -10.0");
+ });
+ }
+
+ private Test CreateRationalBehaviorTest()
+ {
+ return new TestCase(
+ "RationalBehavior",
+ () =>
+ {
+ double[] points, values;
+ SampleProvider.Equidistant(t => 1 / (1 + (t * t)), -5.0, 5.0, 41, out points, out values);
+ var interpolation = Factory(points, values);
+
+ for (int i = 0; i < points.Length; i++)
+ {
+ Assert.AreApproximatelyEqual(
+ values[i],
+ interpolation.Interpolate(points[i]),
+ 1e-12,
+ "Match on knots");
+ }
+
+ double[] testPoints, testValues;
+ SampleProvider.Equidistant(t => 1 / (1 + (t * t)), -5.0, 5.0, 81, out testPoints, out testValues);
+
+ for (int i = 0; i < testPoints.Length; i++)
+ {
+ Assert.AreApproximatelyEqual(
+ testValues[i],
+ interpolation.Interpolate(testPoints[i]),
+ 1e-5,
+ "Match between knots");
+ }
+ });
+ }
+ }
+}
diff --git a/src/UnitTests/InterpolationTests/InterpolationFunctionalTest.cs b/src/UnitTests/InterpolationTests/InterpolationFunctionalTest.cs
new file mode 100644
index 00000000..ea36be81
--- /dev/null
+++ b/src/UnitTests/InterpolationTests/InterpolationFunctionalTest.cs
@@ -0,0 +1,122 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://mathnet.opensourcedotnet.info
+//
+// Copyright (c) 2009 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.UnitTests.InterpolationTests
+{
+ using Interpolation;
+ using Interpolation.Algorithms;
+ using MbUnit.Framework;
+ using MbUnit.Framework.ContractVerifiers;
+
+ [TestFixture]
+ public class InterpolationFunctionalTest
+ {
+ /**** Direct Algorithms (without precomputations) ****/
+
+ [VerifyContract]
+ public readonly IContract NevillePolynomialFunctionalTests =
+ new InterpolationFunctionalContract
+ {
+ Factory = (t, x) => new NevillePolynomialInterpolation(t, x),
+ MinimumSampleCount = 1,
+ LinearBehavior = true,
+ PolynomialBehavior = true,
+ RationalBehavior = false
+ };
+
+ [VerifyContract]
+ public readonly IContract BulirschStoerRationalFunctionalTests =
+ new InterpolationFunctionalContract
+ {
+ Factory = Interpolate.RationalWithPoles,
+ MinimumSampleCount = 1,
+ LinearBehavior = false,
+ PolynomialBehavior = true,
+ RationalBehavior = true
+ };
+
+ /**** Barycentric Algorithms ****/
+
+ [VerifyContract]
+ public readonly IContract FloaterHormannRationalFunctionalTests =
+ new InterpolationFunctionalContract
+ {
+ Factory = Interpolate.RationalWithoutPoles,
+ MinimumSampleCount = 1,
+ LinearBehavior = true,
+ PolynomialBehavior = true,
+ RationalBehavior = true
+ };
+
+ [VerifyContract]
+ public readonly IContract EquidistantPolynomialFunctionalTests =
+ new InterpolationFunctionalContract
+ {
+ Factory = (t, x) => new EquidistantPolynomialInterpolation(t, x),
+ MinimumSampleCount = 1,
+ LinearBehavior = true,
+ PolynomialBehavior = true,
+ RationalBehavior = false
+ };
+
+ /**** Spline Algorithms ****/
+
+ [VerifyContract]
+ public readonly IContract LinearSplineFunctionalTests =
+ new InterpolationFunctionalContract
+ {
+ Factory = Interpolate.LinearBetweenPoints,
+ MinimumSampleCount = 2,
+ LinearBehavior = true,
+ PolynomialBehavior = false,
+ RationalBehavior = false
+ };
+
+ [VerifyContract]
+ public readonly IContract CubicSplineFunctionalTests =
+ new InterpolationFunctionalContract
+ {
+ Factory = (t, x) => new CubicSplineInterpolation(t, x),
+ MinimumSampleCount = 2,
+ LinearBehavior = true,
+ PolynomialBehavior = false,
+ RationalBehavior = false
+ };
+
+ [VerifyContract]
+ public readonly IContract AkimaSplineFunctionalTests =
+ new InterpolationFunctionalContract
+ {
+ Factory = (t, x) => new AkimaSplineInterpolation(t, x),
+ MinimumSampleCount = 5,
+ LinearBehavior = true,
+ PolynomialBehavior = false,
+ RationalBehavior = false
+ };
+ }
+}
diff --git a/src/UnitTests/InterpolationTests/InterpolationInfrastructureContract.cs b/src/UnitTests/InterpolationTests/InterpolationInfrastructureContract.cs
new file mode 100644
index 00000000..45c08c28
--- /dev/null
+++ b/src/UnitTests/InterpolationTests/InterpolationInfrastructureContract.cs
@@ -0,0 +1,265 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://mathnet.opensourcedotnet.info
+//
+// Copyright (c) 2009 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.UnitTests.InterpolationTests
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq.Expressions;
+ using Interpolation;
+ using MbUnit.Framework;
+ using MbUnit.Framework.ContractVerifiers;
+
+ internal class InterpolationInfrastructureContract : AbstractContract
+ where TInterpolation : IInterpolation
+ {
+ public Func[] UninitializedFactories { get; set; }
+ public Expression>[] InitializedFactories { get; set; }
+
+ public int MinimumSampleCount { get; set; }
+
+ protected override IEnumerable GetContractVerificationTests()
+ {
+ yield return CreateLoadUninitializedFactoryTest();
+ yield return CreateLoadInitializedFactoryTest();
+
+ yield return CreateInitializedFactoryChecksForNullTest();
+ yield return CreateInitializedFactoryChecksForToFewSamplesTest();
+ yield return CreateInitializedFactoryChecksForCountMismatchTest();
+
+ yield return CreateConsistentCapabilityBehaviorTest();
+ }
+
+ private Test CreateLoadUninitializedFactoryTest()
+ {
+ return new TestCase(
+ "LoadUninitializedFactory",
+ () =>
+ {
+ Assert.IsNotNull(UninitializedFactories);
+ Assert.LessThan(0, UninitializedFactories.Length);
+
+ foreach (var factory in UninitializedFactories)
+ {
+ var interpolation = factory();
+
+ Assert.IsNotNull(interpolation);
+ Assert.IsInstanceOfType(typeof(TInterpolation), interpolation);
+ }
+ });
+ }
+
+ private Test CreateLoadInitializedFactoryTest()
+ {
+ return new TestCase(
+ "LoadInitializedFactory",
+ () =>
+ {
+ Assert.IsNotNull(InitializedFactories);
+ Assert.LessThan(0, InitializedFactories.Length);
+
+ foreach (var factory in InitializedFactories)
+ {
+ var interpolation = factory.Compile()();
+
+ Assert.IsNotNull(interpolation);
+ Assert.IsInstanceOfType(typeof(TInterpolation), interpolation);
+ Assert.DoesNotThrow(() => interpolation.Interpolate(0.0));
+ }
+ });
+ }
+
+ private Test CreateInitializedFactoryChecksForNullTest()
+ {
+ return new TestCase(
+ "InitializedFactoryChecksForNull",
+ () =>
+ {
+ foreach (var factory in InitializedFactories)
+ {
+ // we only support method calls and constructors for now.
+ if (factory.Body.NodeType != ExpressionType.New
+ && factory.Body.NodeType != ExpressionType.Call)
+ {
+ Assert.Fail(
+ "Factory '{0}' is neither a constructor or a method call.",
+ factory.ToString());
+ continue;
+ }
+
+ var modifiedFactories = factory.ApplySingleMapEachArgument(
+ t => !t.IsValueType,
+ e => Expression.Constant(null, e.Type));
+
+ foreach (var modifiedFactory in modifiedFactories)
+ {
+ var closureFactoryReference = modifiedFactory;
+
+ Assert.Throws(
+ typeof(ArgumentNullException),
+ () => closureFactoryReference.Compile()(),
+ "Factory must check for null arguments ({0})",
+ closureFactoryReference.ToString());
+ }
+ }
+ });
+ }
+
+ private Test CreateInitializedFactoryChecksForToFewSamplesTest()
+ {
+ return new TestCase(
+ "InitializedFactoryChecksForToFewSamples",
+ () =>
+ {
+ foreach (var factory in InitializedFactories)
+ {
+ // we only support method calls and constructors for now.
+ if (factory.Body.NodeType != ExpressionType.New
+ && factory.Body.NodeType != ExpressionType.Call)
+ {
+ Assert.Fail(
+ "Factory '{0}' is neither a constructor or a method call.",
+ factory.ToString());
+ continue;
+ }
+
+ var modifiedFactories = factory.ApplySingleMapEachArgument(
+ t => !t.IsValueType,
+ e => Expression.Constant(new double[MinimumSampleCount - 1], typeof(double[])));
+
+ foreach (var modifiedFactory in modifiedFactories)
+ {
+ var closureFactoryReference = modifiedFactory;
+
+ Assert.Throws(
+ typeof(ArgumentException),
+ () => closureFactoryReference.Compile()(),
+ "Factory must check to ensure there are enough samples ({0})",
+ closureFactoryReference.ToString());
+ }
+ }
+ });
+ }
+
+ private Test CreateInitializedFactoryChecksForCountMismatchTest()
+ {
+ return new TestCase(
+ "InitializedFactoryChecksForCountMismatch",
+ () =>
+ {
+ foreach (var factory in InitializedFactories)
+ {
+ // we only support method calls and constructors for now.
+ if (factory.Body.NodeType != ExpressionType.New
+ && factory.Body.NodeType != ExpressionType.Call)
+ {
+ Assert.Fail(
+ "Factory '{0}' is neither a constructor or a method call.",
+ factory.ToString());
+ continue;
+ }
+
+ // mismatch doesn't make sense when there are less than two list arguments.
+ int listCount = factory.ApplyReduceArgument(
+ (e, count) => typeof(IList).IsAssignableFrom(e.Type) ? count + 1 : count,
+ 0);
+
+ if (listCount < 2)
+ {
+ continue;
+ }
+
+ var modifiedFactories = factory.ApplySingleMapEachArgument(
+ t => !t.IsValueType,
+ e =>
+ {
+ // add a single entry to the end of the list
+ var originalList = Expression.Lambda>(e).Compile()();
+ var newList = new double[originalList.Length + 1];
+ originalList.CopyTo(newList, 0);
+ newList[newList.Length - 1] = -1;
+ return Expression.Constant(newList, e.Type);
+ });
+
+ foreach (var modifiedFactory in modifiedFactories)
+ {
+ var closureFactoryReference = modifiedFactory;
+
+ Assert.Throws(
+ typeof(ArgumentException),
+ () => closureFactoryReference.Compile()(),
+ "Factory must check for matching sample lengths ({0})",
+ closureFactoryReference.ToString());
+ }
+ }
+ });
+ }
+
+ private Test CreateConsistentCapabilityBehaviorTest()
+ {
+ return new TestCase(
+ "ConsistentCapabilityBehavior",
+ () =>
+ {
+ var interpolation = InitializedFactories[0].Compile()();
+
+ // verify consistent differentiation capability
+ if (interpolation.SupportsDifferentiation)
+ {
+ double a, b;
+ Assert.DoesNotThrow(() => interpolation.Differentiate(1.2));
+ Assert.DoesNotThrow(() => interpolation.Differentiate(1.2, out a, out b));
+ }
+ else
+ {
+ double a, b;
+
+ Assert.Throws(
+ typeof(NotSupportedException),
+ () => interpolation.Differentiate(1.2));
+
+ Assert.Throws(
+ typeof(NotSupportedException),
+ () => interpolation.Differentiate(1.2, out a, out b));
+ }
+
+ // verify consistent integration capability
+ if (interpolation.SupportsIntegration)
+ {
+ Assert.DoesNotThrow(() => interpolation.Integrate(1.2));
+ }
+ else
+ {
+ Assert.Throws(
+ typeof(NotSupportedException),
+ () => interpolation.Integrate(1.2));
+ }
+ });
+ }
+ }
+}
diff --git a/src/UnitTests/InterpolationTests/InterpolationInfrastuctureTest.cs b/src/UnitTests/InterpolationTests/InterpolationInfrastuctureTest.cs
new file mode 100644
index 00000000..31b0722c
--- /dev/null
+++ b/src/UnitTests/InterpolationTests/InterpolationInfrastuctureTest.cs
@@ -0,0 +1,343 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://mathnet.opensourcedotnet.info
+//
+// Copyright (c) 2009 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.UnitTests.InterpolationTests
+{
+ using System;
+ using System.Linq.Expressions;
+ using Interpolation;
+ using Interpolation.Algorithms;
+ using MbUnit.Framework;
+ using MbUnit.Framework.ContractVerifiers;
+
+ [TestFixture]
+ public class InterpolationInfrastuctureTest
+ {
+ /**** Direct Algorithms (without precomputations) ****/
+
+ [VerifyContract]
+ public readonly IContract NevillePolynomialInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 1,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new NevillePolynomialInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new NevillePolynomialInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5))
+ }
+ };
+
+ [VerifyContract]
+ public readonly IContract BulirschStoerRationalInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 1,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new BulirschStoerRationalInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new BulirschStoerRationalInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5)),
+ () => Interpolate.RationalWithPoles(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5))
+ }
+ };
+
+ /**** Barycentric Algorithms ****/
+
+ [VerifyContract]
+ public readonly IContract BarycentricInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 3,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new BarycentricInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new BarycentricInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5),
+ SampleProvider.LinearEquidistant(10, 1, 0.1)),
+ () => new BarycentricInterpolation(
+ SampleProvider.LinearEquidistant(10, 5, -1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5),
+ SampleProvider.LinearEquidistant(10, 1, 0.1))
+ }
+ };
+
+ [VerifyContract]
+ public readonly IContract FloaterHormannRationalInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 1,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new FloaterHormannRationalInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new FloaterHormannRationalInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5)),
+ () => new FloaterHormannRationalInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5),
+ 5),
+ () => Interpolate.RationalWithoutPoles(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5)),
+ () => Interpolate.Common(
+ SampleProvider.LinearEquidistant(10, 5, -1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5))
+ }
+ };
+
+ [VerifyContract]
+ public readonly IContract EquidistantPolynomialInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 1,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new EquidistantPolynomialInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new EquidistantPolynomialInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5)),
+ () => new EquidistantPolynomialInterpolation(
+ SampleProvider.LinearEquidistant(10, 5, -1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5)),
+ () => new EquidistantPolynomialInterpolation(
+ -5,
+ 4,
+ SampleProvider.LinearEquidistant(10, -2, 0.5))
+ }
+ };
+
+ /**** Spline Algorithms ****/
+
+ [VerifyContract]
+ public readonly IContract SplineInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 2,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new SplineInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new SplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(4 * (10 - 1), -2, 0.5)),
+ () => new SplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ AkimaSplineInterpolation.EvaluateSplineCoefficients(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5))),
+ () => new SplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ CubicSplineInterpolation.EvaluateSplineCoefficients(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5),
+ SplineBoundaryCondition.Natural,
+ 1.0,
+ SplineBoundaryCondition.Natural,
+ -1.0))
+ }
+ };
+
+ [VerifyContract]
+ public readonly IContract CubicHermiteSplineInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 2,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new CubicHermiteSplineInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new CubicHermiteSplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5),
+ SampleProvider.LinearEquidistant(10, 1, 0.1))
+ }
+ };
+
+ [VerifyContract]
+ public readonly IContract LinearSplineInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 2,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new LinearSplineInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new LinearSplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5)),
+ () => Interpolate.LinearBetweenPoints(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5))
+ }
+ };
+
+ [VerifyContract]
+ public readonly IContract CubicSplineInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 2,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new CubicSplineInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new CubicSplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5)),
+ () => new CubicSplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5),
+ SplineBoundaryCondition.FirstDerivative,
+ 1.0,
+ SplineBoundaryCondition.FirstDerivative,
+ -1.0),
+ () => new CubicSplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5),
+ SplineBoundaryCondition.Natural,
+ 1.0,
+ SplineBoundaryCondition.Natural,
+ -1.0),
+ () => new CubicSplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5),
+ SplineBoundaryCondition.ParabolicallyTerminated,
+ 1.0,
+ SplineBoundaryCondition.ParabolicallyTerminated,
+ -1.0),
+ () => new CubicSplineInterpolation(
+ SampleProvider.LinearEquidistant(2, -5, 1),
+ SampleProvider.LinearEquidistant(2, -2, 0.5),
+ SplineBoundaryCondition.ParabolicallyTerminated,
+ 1.0,
+ SplineBoundaryCondition.ParabolicallyTerminated,
+ -1.0)
+ }
+ };
+
+ [VerifyContract]
+ public readonly IContract AkimaSplineInfrastructureTests =
+ new InterpolationInfrastructureContract
+ {
+ MinimumSampleCount = 5,
+ UninitializedFactories =
+ new Func[]
+ {
+ () => new AkimaSplineInterpolation()
+ },
+ InitializedFactories =
+ new Expression>[]
+ {
+ () => new AkimaSplineInterpolation(
+ SampleProvider.LinearEquidistant(10, -5, 1),
+ SampleProvider.LinearEquidistant(10, -2, 0.5))
+ }
+ };
+
+ [Test]
+ public void FloaterHormannRationalThrowsOnBadOrder()
+ {
+ Assert.Throws(
+ typeof(ArgumentOutOfRangeException),
+ () => new FloaterHormannRationalInterpolation(
+ new double[5],
+ new double[5],
+ 10));
+ }
+
+ [Test]
+ public void CubicSplineThrowsOnBadBoundaryCondition()
+ {
+ Assert.Throws(
+ typeof(NotSupportedException),
+ () => new CubicSplineInterpolation(
+ new double[5],
+ new double[5],
+ (SplineBoundaryCondition)(-1),
+ 0,
+ SplineBoundaryCondition.Natural,
+ 0));
+
+ Assert.Throws(
+ typeof(NotSupportedException),
+ () => new CubicSplineInterpolation(
+ new double[5],
+ new double[5],
+ SplineBoundaryCondition.Natural,
+ 0,
+ (SplineBoundaryCondition)(-1),
+ 0));
+ }
+ }
+}
diff --git a/src/UnitTests/InterpolationTests/InterpolationTest.cs b/src/UnitTests/InterpolationTests/InterpolationTest.cs
deleted file mode 100644
index 1c733696..00000000
--- a/src/UnitTests/InterpolationTests/InterpolationTest.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-//
-// Math.NET Numerics, part of the Math.NET Project
-// http://mathnet.opensourcedotnet.info
-//
-// Copyright (c) 2009 Math.NET
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use,
-// copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following
-// conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-//
-
-namespace MathNet.Numerics.UnitTests.InterpolationTests
-{
- using System;
- using Interpolation;
- using Interpolation.Algorithms;
- using MbUnit.Framework;
- using MbUnit.Framework.ContractVerifiers;
-
- [TestFixture]
- public class InterpolationTest
- {
- // Direct Algorithms (without precomputations)
-
- [VerifyContract]
- public readonly IContract NevillePolynomialContractTests = new InterpolationContract()
- {
- Factory = (t, x) => new NevillePolynomialInterpolation(t, x),
- MinimumSampleCount = 1,
- LinearBehavior = true,
- PolynomialBehavior = true,
- RationalBehavior = false
- };
-
- [VerifyContract]
- public readonly IContract BulirschStoerRationalContractTests = new InterpolationContract()
- {
- Factory = Interpolate.RationalWithPoles,
- MinimumSampleCount = 1,
- LinearBehavior = false,
- PolynomialBehavior = true,
- RationalBehavior = true
- };
-
- // Barycentric Algorithms
-
- [VerifyContract]
- public readonly IContract BarycentricContractTests = new InterpolationContract()
- {
- Factory = (t, x) => new BarycentricInterpolation(t, x, FloaterHormannRationalInterpolation.EvaluateBarycentricWeights(t, x, 2)),
- MinimumSampleCount = 3,
- NonStandardParameters = true,
- };
-
- [VerifyContract]
- public readonly IContract FloaterHormannRationalContractTests = new InterpolationContract()
- {
- Factory = Interpolate.RationalWithoutPoles,
- MinimumSampleCount = 1,
- LinearBehavior = true,
- PolynomialBehavior = true,
- RationalBehavior = true
- };
-
- // Spline Algorithms
-
- [VerifyContract]
- public readonly IContract SplineContractTests = new InterpolationContract()
- {
- Factory = (t, x) => new SplineInterpolation(t, LinearSplineInterpolation.EvaluateSplineCoefficients(t, x)),
- MinimumSampleCount = 2,
- NonStandardParameters = true,
- };
-
- [VerifyContract]
- public readonly IContract CubicHermiteSplineContractTests = new InterpolationContract()
- {
- Factory = (t, x) => new CubicHermiteSplineInterpolation(t, x, CubicSplineInterpolation.EvaluateSplineDerivatives(t, x, SplineBoundaryCondition.Natural, 0.0, SplineBoundaryCondition.Natural, 0.0)),
- MinimumSampleCount = 2,
- NonStandardParameters = true,
- };
-
- [VerifyContract]
- public readonly IContract LinearSplineContractTests = new InterpolationContract()
- {
- Factory = Interpolate.LinearBetweenPoints,
- MinimumSampleCount = 2,
- LinearBehavior = true,
- PolynomialBehavior = false,
- RationalBehavior = false
- };
-
- [VerifyContract]
- public readonly IContract CubicSplineContractTests = new InterpolationContract()
- {
- Factory = (t, x) => new CubicSplineInterpolation(t, x),
- MinimumSampleCount = 2,
- LinearBehavior = true,
- PolynomialBehavior = false,
- RationalBehavior = false
- };
-
- [VerifyContract]
- public readonly IContract AkimaSplineContractTests = new InterpolationContract()
- {
- Factory = (t, x) => new AkimaSplineInterpolation(t, x),
- MinimumSampleCount = 5,
- LinearBehavior = true,
- PolynomialBehavior = false,
- RationalBehavior = false
- };
- }
-}
diff --git a/src/UnitTests/InterpolationTests/SampleProvider.cs b/src/UnitTests/InterpolationTests/SampleProvider.cs
new file mode 100644
index 00000000..abd8903d
--- /dev/null
+++ b/src/UnitTests/InterpolationTests/SampleProvider.cs
@@ -0,0 +1,81 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://mathnet.opensourcedotnet.info
+//
+// Copyright (c) 2009 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.UnitTests.InterpolationTests
+{
+ using System;
+
+ internal static class SampleProvider
+ {
+ internal static double[] LinearEquidistant(int count, double start, double step)
+ {
+ var samples = new double[count];
+ var nextValue = start;
+
+ for (int i = 0; i < samples.Length; i++)
+ {
+ samples[i] = nextValue;
+ nextValue += step;
+ }
+
+ return samples;
+ }
+
+ internal static void Equidistant(
+ Func f,
+ double start,
+ double stop,
+ int samples,
+ out double[] points,
+ out double[] values)
+ {
+ points = new double[samples];
+ values = new double[samples];
+
+ if (samples == 0)
+ {
+ return;
+ }
+
+ if (samples == 1)
+ {
+ double t = points[0] = 0.5 * (start + stop);
+ values[0] = f(t);
+ return;
+ }
+
+ double step = (stop - start) / (samples - 1);
+ for (int i = 0; i < points.Length; i++)
+ {
+ double t = start + (i * step);
+ points[i] = t;
+ values[i] = f(t);
+ }
+ }
+ }
+}
diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj
index fe292ad0..74f53267 100644
--- a/src/UnitTests/UnitTests.csproj
+++ b/src/UnitTests/UnitTests.csproj
@@ -74,8 +74,12 @@
-
-
+
+
+
+
+
+