Author: luc
Date: Tue Aug 14 09:45:36 2012
New Revision: 1372812
URL: http://svn.apache.org/viewvc?rev=1372812&view=rev
Log:
Simplified tangent higher derivatives computation.
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/analysis/differentiation/DSCompiler.java
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/analysis/differentiation/DSCompiler.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/analysis/differentiation/DSCompiler.java?rev=1372812&r1=1372811&r2=1372812&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/analysis/differentiation/DSCompiler.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/analysis/differentiation/DSCompiler.java
Tue Aug 14 09:45:36 2012
@@ -1066,33 +1066,41 @@ public class DSCompiler {
final double[] result, final int resultOffset) {
// create the function value and derivatives
- double[] function = new double[1 + order];
- final double z = operand[operandOffset];
- final double t = FastMath.tan(z);
+ final double[] function = new double[1 + order];
+ final double t = FastMath.tan(operand[operandOffset]);
function[0] = t;
+
if (order > 0) {
- final double secant2 = 1 + t * t;
- function[1] = secant2;
- for (int n = 2; n <= order; ++n) {
- final int signN4 = ((n & 0x02) == 0) ? 1 : -1;
- double outerSum = 0;
- int sign = 1;
- double secant2Kp2 = secant2;
- for (int k = 0; k < n; ++k) {
- double innerSum = 0;
- for (int j = 0; j < k; ++j) {
- final double alpha = 2 * (k - j) * z;
- final double sc = ((n & 0x01) == 0) ?
FastMath.sin(alpha) : FastMath.cos(alpha);
- innerSum += sc * signN4 * ArithmeticUtils.pow(k - j,
n - 1) *
- ArithmeticUtils.binomialCoefficient(2 * k,
j);
+
+ // the nth order derivative of tan has the form:
+ // dn(tan(x)/dxn = P_n(tan(x))
+ // where P_n(t) is a degree n+1 polynomial with same parity as n+1
+ // P_0(t) = t, P_1(t) = 1 + t^2, P_2(x) = 2 t (1 + t^2) ...
+ // the general recurrence relation for P_n is:
+ // P_n(x) = (1+t^2) P_(n-1)'(t)
+ // as per polynomial parity, we can store coefficients of both
P_(n-1) and P_n in the same array
+ final double[] p = new double[order + 2];
+ p[1] = 1;
+ final double t2 = t * t;
+ for (int n = 1; n <= order; ++n) {
+
+ // update and evaluate polynomial P_n(t)
+ double v = 0;
+ p[n + 1] = n * p[n];
+ for (int k = n + 1; k >= 0; k -= 2) {
+ v = v * t2 + p[k];
+ if (k > 2) {
+ p[k - 2] = (k - 1) * p[k - 1] + (k - 3) * p[k - 3];
+ } else if (k == 2) {
+ p[0] = p[1];
}
- double twoNm2K = (n >= 2 * k) ? (1 << (n - 2 * k)) : (1.0
/ (1 << (2 * k - n)));
- outerSum += sign * innerSum *
ArithmeticUtils.binomialCoefficient(n - 1, k) *
- twoNm2K * secant2Kp2 / (k + 1);
- sign = -sign;
- secant2Kp2 *= secant2;
}
- function[n] = n * outerSum;
+ if ((n & 0x1) == 0) {
+ v *= t;
+ }
+
+ function[n] = v;
+
}
}