From b84754cc7f06aeab1231dc6c09f2aa6166d56334 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe Date: Mon, 25 Feb 2013 19:31:52 +0000 Subject: [PATCH] Added derivatives evaluation for field Hermite interpolator. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1449822 13f79535-47bb-0310-9956-ffa450edef68 --- .../FieldHermiteInterpolator.java | 45 +++++++++++++++++++ .../FieldHermiteInterpolatorTest.java | 39 ++++++++++++++-- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/apache/commons/math3/analysis/interpolation/FieldHermiteInterpolator.java b/src/main/java/org/apache/commons/math3/analysis/interpolation/FieldHermiteInterpolator.java index ffd01f050..861da6090 100644 --- a/src/main/java/org/apache/commons/math3/analysis/interpolation/FieldHermiteInterpolator.java +++ b/src/main/java/org/apache/commons/math3/analysis/interpolation/FieldHermiteInterpolator.java @@ -149,4 +149,49 @@ public class FieldHermiteInterpolator> { } + /** Interpolate value and first derivatives at a specified abscissa. + * @param x interpolation abscissa + * @param order maximum derivation order + * @return interpolated value and derivatives (value in row 0, + * 1st derivative in row 1, ... nth derivative in row n) + * @exception NoDataException if sample is empty + */ + public T[][] derivatives(T x, int order) throws NoDataException { + + // safety check + if (abscissae.isEmpty()) { + throw new NoDataException(LocalizedFormats.EMPTY_INTERPOLATION_SAMPLE); + } + + final T zero = x.getField().getZero(); + final T one = x.getField().getOne(); + final T[] tj = MathArrays.buildArray(x.getField(), order + 1); + tj[0] = zero; + for (int i = 0; i < order; ++i) { + tj[i + 1] = tj[i].add(one); + } + + final T[][] derivatives = + MathArrays.buildArray(x.getField(), order + 1, topDiagonal.get(0).length); + final T[] valueCoeff = MathArrays.buildArray(x.getField(), order + 1); + valueCoeff[0] = x.getField().getOne(); + for (int i = 0; i < topDiagonal.size(); ++i) { + T[] dividedDifference = topDiagonal.get(i); + final T deltaX = x.subtract(abscissae.get(i)); + for (int j = order; j >= 0; --j) { + for (int k = 0; k < derivatives[j].length; ++k) { + derivatives[j][k] = + derivatives[j][k].add(dividedDifference[k].multiply(valueCoeff[j])); + } + valueCoeff[j] = valueCoeff[j].multiply(deltaX); + if (j > 0) { + valueCoeff[j] = valueCoeff[j].add(tj[j].multiply(valueCoeff[j - 1])); + } + } + } + + return derivatives; + + } + } diff --git a/src/test/java/org/apache/commons/math3/analysis/interpolation/FieldHermiteInterpolatorTest.java b/src/test/java/org/apache/commons/math3/analysis/interpolation/FieldHermiteInterpolatorTest.java index ea022c0aa..2acaa8d4f 100644 --- a/src/test/java/org/apache/commons/math3/analysis/interpolation/FieldHermiteInterpolatorTest.java +++ b/src/test/java/org/apache/commons/math3/analysis/interpolation/FieldHermiteInterpolatorTest.java @@ -36,6 +36,9 @@ public class FieldHermiteInterpolatorTest { for (int x = -10; x < 10; x++) { BigFraction y = interpolator.value(new BigFraction(x))[0]; Assert.assertEquals(BigFraction.ZERO, y); + BigFraction[][] derivatives = interpolator.derivatives(new BigFraction(x), 1); + Assert.assertEquals(BigFraction.ZERO, derivatives[0][0]); + Assert.assertEquals(BigFraction.ZERO, derivatives[1][0]); } } @@ -48,6 +51,11 @@ public class FieldHermiteInterpolatorTest { for (double x = -10; x < 10; x += 1.0) { BigFraction y = interpolator.value(new BigFraction(x))[0]; Assert.assertEquals((x - 1) * (x - 2), y.doubleValue(), 1.0e-15); + BigFraction[][] derivatives = interpolator.derivatives(new BigFraction(x), 3); + Assert.assertEquals((x - 1) * (x - 2), derivatives[0][0].doubleValue(), 1.0e-15); + Assert.assertEquals(2 * x - 3, derivatives[1][0].doubleValue(), 1.0e-15); + Assert.assertEquals(2, derivatives[2][0].doubleValue(), 1.0e-15); + Assert.assertEquals(0, derivatives[3][0].doubleValue(), 1.0e-15); } } @@ -57,9 +65,27 @@ public class FieldHermiteInterpolatorTest { interpolator.addSamplePoint(new BigFraction(0), new BigFraction[] { new BigFraction(1) }, new BigFraction[] { new BigFraction(2) }); interpolator.addSamplePoint(new BigFraction(1), new BigFraction[] { new BigFraction(4) }); interpolator.addSamplePoint(new BigFraction(2), new BigFraction[] { new BigFraction(5) }, new BigFraction[] { new BigFraction(2) }); - Assert.assertEquals(new BigFraction(1), interpolator.value(new BigFraction(0))[0]); - Assert.assertEquals(new BigFraction(4), interpolator.value(new BigFraction(1))[0]); - Assert.assertEquals(new BigFraction(5), interpolator.value(new BigFraction(2))[0]); + BigFraction[][] derivatives = interpolator.derivatives(new BigFraction(0), 5); + Assert.assertEquals(new BigFraction( 1), derivatives[0][0]); + Assert.assertEquals(new BigFraction( 2), derivatives[1][0]); + Assert.assertEquals(new BigFraction( 8), derivatives[2][0]); + Assert.assertEquals(new BigFraction(-24), derivatives[3][0]); + Assert.assertEquals(new BigFraction( 24), derivatives[4][0]); + Assert.assertEquals(new BigFraction( 0), derivatives[5][0]); + derivatives = interpolator.derivatives(new BigFraction(1), 5); + Assert.assertEquals(new BigFraction( 4), derivatives[0][0]); + Assert.assertEquals(new BigFraction( 2), derivatives[1][0]); + Assert.assertEquals(new BigFraction( -4), derivatives[2][0]); + Assert.assertEquals(new BigFraction( 0), derivatives[3][0]); + Assert.assertEquals(new BigFraction( 24), derivatives[4][0]); + Assert.assertEquals(new BigFraction( 0), derivatives[5][0]); + derivatives = interpolator.derivatives(new BigFraction(2), 5); + Assert.assertEquals(new BigFraction( 5), derivatives[0][0]); + Assert.assertEquals(new BigFraction( 2), derivatives[1][0]); + Assert.assertEquals(new BigFraction( 8), derivatives[2][0]); + Assert.assertEquals(new BigFraction( 24), derivatives[3][0]); + Assert.assertEquals(new BigFraction( 24), derivatives[4][0]); + Assert.assertEquals(new BigFraction( 0), derivatives[5][0]); } @Test @@ -230,10 +256,15 @@ public class FieldHermiteInterpolatorTest { } @Test(expected=NoDataException.class) - public void testEmptySample() { + public void testEmptySampleValue() { new FieldHermiteInterpolator().value(BigFraction.ZERO); } + @Test(expected=NoDataException.class) + public void testEmptySampleDerivative() { + new FieldHermiteInterpolator().derivatives(BigFraction.ZERO, 1); + } + @Test(expected=IllegalArgumentException.class) public void testDuplicatedAbscissa() { FieldHermiteInterpolator interpolator = new FieldHermiteInterpolator();