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
This commit is contained in:
Luc Maisonobe 2013-02-25 19:31:52 +00:00
parent f4e9bfe99f
commit b84754cc7f
2 changed files with 80 additions and 4 deletions

View File

@ -149,4 +149,49 @@ public class FieldHermiteInterpolator<T extends FieldElement<T>> {
}
/** 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,
* 1<sup>st</sup> derivative in row 1, ... n<sup>th</sup> 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;
}
}

View File

@ -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<BigFraction>().value(BigFraction.ZERO);
}
@Test(expected=NoDataException.class)
public void testEmptySampleDerivative() {
new FieldHermiteInterpolator<BigFraction>().derivatives(BigFraction.ZERO, 1);
}
@Test(expected=IllegalArgumentException.class)
public void testDuplicatedAbscissa() {
FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();