Added "derivative".
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1183373 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
dacfe6588c
commit
852879bd56
|
@ -18,6 +18,7 @@
|
|||
package org.apache.commons.math.analysis.function;
|
||||
|
||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||
import org.apache.commons.math.analysis.DifferentiableUnivariateRealFunction;
|
||||
import org.apache.commons.math.util.FastMath;
|
||||
|
||||
/**
|
||||
|
@ -31,7 +32,13 @@ import org.apache.commons.math.util.FastMath;
|
|||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public class Sinc implements UnivariateRealFunction {
|
||||
public class Sinc implements DifferentiableUnivariateRealFunction {
|
||||
/**
|
||||
* Value below which the result of the computation will not change
|
||||
* anymore due to the finite precision of the "double" representation
|
||||
* of real numbers.
|
||||
*/
|
||||
private static final double SHORTCUT = 1e-9;
|
||||
/** For normalized sinc function. */
|
||||
private final boolean normalized;
|
||||
|
||||
|
@ -62,6 +69,26 @@ public class Sinc implements UnivariateRealFunction {
|
|||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public UnivariateRealFunction derivative() {
|
||||
if (normalized) {
|
||||
return new UnivariateRealFunction() {
|
||||
/** {@inheritDoc} */
|
||||
public double value(double x) {
|
||||
final double piTimesX = Math.PI * x;
|
||||
return sincDerivative(piTimesX);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return new UnivariateRealFunction() {
|
||||
/** {@inheritDoc} */
|
||||
public double value(double x) {
|
||||
return sincDerivative(x);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x Argument.
|
||||
* @return {@code sin(x) / x}.
|
||||
|
@ -71,6 +98,20 @@ public class Sinc implements UnivariateRealFunction {
|
|||
// optimization on the ground that the result of the full computation
|
||||
// is indistinguishable from 1 due to the limited accuracy of the
|
||||
// floating point representation.
|
||||
return FastMath.abs(x) < 1e-9 ? 1 : FastMath.sin(x) / x;
|
||||
return FastMath.abs(x) < SHORTCUT ? 1 :
|
||||
FastMath.sin(x) / x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x Argument.
|
||||
* @return {@code (cos(x) - sin(x) / x) / x}.
|
||||
*/
|
||||
private static double sincDerivative(double x) {
|
||||
// The direct assignment to 0 for values below 1e-9 is an efficiency
|
||||
// optimization on the ground that the result of the full computation
|
||||
// is indistinguishable from 1 due to the limited accuracy of the
|
||||
// floating point representation.
|
||||
return FastMath.abs(x) < SHORTCUT ? 0 :
|
||||
(FastMath.cos(x) - FastMath.sin(x) / x) / x;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public class SincTest {
|
|||
}
|
||||
};
|
||||
|
||||
for (double x = 1e-30; x < 1e10; x *= 5) {
|
||||
for (double x = 1e-30; x < 1e10; x *= 2) {
|
||||
final double fX = f.value(x);
|
||||
final double sX = s.value(x);
|
||||
Assert.assertEquals("x=" + x, fX, sX, 0);
|
||||
|
@ -69,4 +69,27 @@ public class SincTest {
|
|||
}
|
||||
Assert.assertEquals(prod, s.value(x), 1e-13);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDerivativeZero() {
|
||||
final UnivariateRealFunction sPrime = (new Sinc(true)).derivative();
|
||||
|
||||
Assert.assertEquals(0, sPrime.value(0), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDerivativeShortcut() {
|
||||
final UnivariateRealFunction sPrime = (new Sinc()).derivative();
|
||||
final UnivariateRealFunction f = new UnivariateRealFunction() {
|
||||
public double value(double x) {
|
||||
return (FastMath.cos(x) - FastMath.sin(x) / x) / x;
|
||||
}
|
||||
};
|
||||
|
||||
for (double x = 1e-30; x < 1e10; x *= 2) {
|
||||
final double fX = f.value(x);
|
||||
final double sX = sPrime.value(x);
|
||||
Assert.assertEquals("x=" + x, fX, sX, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue