From 71756c6599bd57b7e81ecab4173f8d1dd12aba22 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Fri, 14 Aug 2009 18:11:32 +0800 Subject: [PATCH] quadrature: tests now verify argument checks Signed-off-by: Christoph Ruegg --- .../DoubleExponentialTransformation.cs | 4 +- .../Algorithms/NewtonCotesTrapeziumRule.cs | 30 +++++++++ .../Integration/Algorithms/SimpsonRule.cs | 14 ++++- .../IntegrationTests/IntegrationTest.cs | 62 ++++++++++++++++++- 4 files changed, 105 insertions(+), 5 deletions(-) diff --git a/src/Numerics/Integration/Algorithms/DoubleExponentialTransformation.cs b/src/Numerics/Integration/Algorithms/DoubleExponentialTransformation.cs index e9458a0c..06a3d187 100644 --- a/src/Numerics/Integration/Algorithms/DoubleExponentialTransformation.cs +++ b/src/Numerics/Integration/Algorithms/DoubleExponentialTransformation.cs @@ -535,7 +535,7 @@ namespace MathNet.Numerics.Integration.Algorithms /// Abscissa vector per level provider. /// /// Level Enumerator. - private static IEnumerable ProvideLevelAbcissas() + internal static IEnumerable ProvideLevelAbcissas() { for (int i = 0; i < NumberOfMaximumLevels; i++) { @@ -547,7 +547,7 @@ namespace MathNet.Numerics.Integration.Algorithms /// Weight vector per level provider. /// /// Level Enumerator. - private static IEnumerable ProvideLevelWeights() + internal static IEnumerable ProvideLevelWeights() { for (int i = 0; i < NumberOfMaximumLevels; i++) { diff --git a/src/Numerics/Integration/Algorithms/NewtonCotesTrapeziumRule.cs b/src/Numerics/Integration/Algorithms/NewtonCotesTrapeziumRule.cs index a3b5cc91..5b2d6902 100644 --- a/src/Numerics/Integration/Algorithms/NewtonCotesTrapeziumRule.cs +++ b/src/Numerics/Integration/Algorithms/NewtonCotesTrapeziumRule.cs @@ -52,6 +52,11 @@ namespace MathNet.Numerics.Integration.Algorithms double intervalBegin, double intervalEnd) { + if (f == null) + { + throw new ArgumentNullException("f"); + } + return (intervalEnd - intervalBegin) / 2 * (f(intervalBegin) + f(intervalEnd)); } @@ -69,6 +74,11 @@ namespace MathNet.Numerics.Integration.Algorithms double intervalEnd, int numberOfPartitions) { + if (f == null) + { + throw new ArgumentNullException("f"); + } + if (numberOfPartitions <= 0) { throw new ArgumentOutOfRangeException("numberOfPartitions", Resources.ArgumentPositive); @@ -102,6 +112,11 @@ namespace MathNet.Numerics.Integration.Algorithms double intervalEnd, double targetError) { + if (f == null) + { + throw new ArgumentNullException("f"); + } + int numberOfPartitions = 1; double step = intervalEnd - intervalBegin; double sum = 0.5 * step * (f(intervalBegin) + f(intervalEnd)); @@ -147,6 +162,21 @@ namespace MathNet.Numerics.Integration.Algorithms double levelOneStep, double targetRelativeError) { + if (f == null) + { + throw new ArgumentNullException("f"); + } + + if (levelAbscissas == null) + { + throw new ArgumentNullException("levelAbscissas"); + } + + if (levelWeights == null) + { + throw new ArgumentNullException("levelWeights"); + } + double linearSlope = 0.5 * (intervalEnd - intervalBegin); double linearOffset = 0.5 * (intervalEnd + intervalBegin); targetRelativeError /= 5 * linearSlope; diff --git a/src/Numerics/Integration/Algorithms/SimpsonRule.cs b/src/Numerics/Integration/Algorithms/SimpsonRule.cs index 1d2def00..bc563d14 100644 --- a/src/Numerics/Integration/Algorithms/SimpsonRule.cs +++ b/src/Numerics/Integration/Algorithms/SimpsonRule.cs @@ -49,6 +49,11 @@ namespace MathNet.Numerics.Integration.Algorithms double intervalBegin, double intervalEnd) { + if (f == null) + { + throw new ArgumentNullException("f"); + } + double midpoint = (intervalEnd + intervalBegin) / 2; return (intervalEnd - intervalBegin) / 6 * (f(intervalBegin) + f(intervalEnd) + (4 * f(midpoint))); } @@ -67,6 +72,11 @@ namespace MathNet.Numerics.Integration.Algorithms double intervalEnd, int numberOfPartitions) { + if (f == null) + { + throw new ArgumentNullException("f"); + } + if (numberOfPartitions <= 0) { throw new ArgumentOutOfRangeException("numberOfPartitions", Resources.ArgumentPositive); @@ -85,7 +95,7 @@ namespace MathNet.Numerics.Integration.Algorithms double sum = f(intervalBegin) + f(intervalEnd); for (int i = 0; i < numberOfPartitions - 1; i++) { - // NOTE (ruegg, 2009-01-07): Do not combine intervalBegin and offset (numerical stability) + // NOTE (cdrnet, 2009-01-07): Do not combine intervalBegin and offset (numerical stability) sum += m * f(intervalBegin + offset); m = 6 - m; offset += step; @@ -94,4 +104,4 @@ namespace MathNet.Numerics.Integration.Algorithms return factor * sum; } } -} \ No newline at end of file +} diff --git a/src/UnitTests/IntegrationTests/IntegrationTest.cs b/src/UnitTests/IntegrationTests/IntegrationTest.cs index e2dee5d8..0038941a 100644 --- a/src/UnitTests/IntegrationTests/IntegrationTest.cs +++ b/src/UnitTests/IntegrationTests/IntegrationTest.cs @@ -26,13 +26,14 @@ // OTHER DEALINGS IN THE SOFTWARE. // - namespace MathNet.Numerics.UnitTests.IntegrationTests { using System; + using System.Linq.Expressions; using Integration; using Integration.Algorithms; using MbUnit.Framework; + using MbUnit.Framework.ContractVerifiers; [TestFixture] public class IntegrationTest @@ -65,6 +66,18 @@ namespace MathNet.Numerics.UnitTests.IntegrationTests "Basic Target 1e-10"); } + [VerifyContract] + public readonly IContract FacadeIntegrateChecksArguments = + new ArgumentCheckContract + { + TypicalUses = + new Expression>[] + { + () => Integrate.OnClosedInterval(x => 2 * x, StartA, StopA), + () => Integrate.OnClosedInterval(x => 2 * x, StartA, StopA, 1e-5) + } + }; + [Test] [Row(1e-5)] [Row(1e-13)] @@ -79,6 +92,13 @@ namespace MathNet.Numerics.UnitTests.IntegrationTests "DET Adaptive {0}", targetRelativeError); } + [VerifyContract] + public readonly IContract DoubleExponentialTransformationIntegrateChecksArguments = + new ArgumentCheckContract + { + TypicalUse = () => (new DoubleExponentialTransformation()).Integrate(x => 2 * x, StartA, StopA, 1e-5) + }; + [Test] public void TrapeziumRuleSupportsTwoPointIntegration() { @@ -117,6 +137,28 @@ namespace MathNet.Numerics.UnitTests.IntegrationTests "Adaptive {0}", targetRelativeError); } + [VerifyContract] + public readonly IContract TrapeziumRuleIntegrateChecksArguments = + new ArgumentCheckContract + { + TypicalUses = + new Expression>[] + { + () => NewtonCotesTrapeziumRule.IntegrateTwoPoint(x => 2 * x, StartA, StopA), + () => NewtonCotesTrapeziumRule.IntegrateComposite(x => 2 * x, StartA, StopA, 2), + () => NewtonCotesTrapeziumRule.IntegrateAdaptive(x => 2 * x, StartA, StopA, 1e-5), + () => NewtonCotesTrapeziumRule.IntegrateAdaptiveTransformedOdd( + x => 2 * x, + StartA, + StopA, + DoubleExponentialTransformation.ProvideLevelAbcissas(), + DoubleExponentialTransformation.ProvideLevelWeights(), + 1, + 1e-5) + }, + BadUse = () => NewtonCotesTrapeziumRule.IntegrateComposite(x => 2 * x, StartA, StopA, 0) + }; + [Test] public void SimpsonRuleSupportsThreePointIntegration() { @@ -141,5 +183,23 @@ namespace MathNet.Numerics.UnitTests.IntegrationTests maxRelativeError * TargetAreaA, "Composite {0} Partitions", partitions); } + + [VerifyContract] + public readonly IContract SimpsonRuleIntegrateChecksArguments = + new ArgumentCheckContract + { + TypicalUses = + new Expression>[] + { + () => SimpsonRule.IntegrateThreePoint(x => 2 * x, StartA, StopA), + () => SimpsonRule.IntegrateComposite(x => 2 * x, StartA, StopA, 2) + }, + BadUses = + new Func[] + { + () => SimpsonRule.IntegrateComposite(x => 2 * x, StartA, StopA, 0), + () => SimpsonRule.IntegrateComposite(x => 2 * x, StartA, StopA, 3) + } + }; } }