commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From l..@apache.org
Subject svn commit: r1371805 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math3/analysis/differentiation/DSCompiler.java test/java/org/apache/commons/math3/analysis/differentiation/DerivativeStructureTest.java
Date Fri, 10 Aug 2012 18:33:06 GMT
Author: luc
Date: Fri Aug 10 18:33:06 2012
New Revision: 1371805

URL: http://svn.apache.org/viewvc?rev=1371805&view=rev
Log:
Completed support fo asin, acos and atan in DSCompiler.

Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/analysis/differentiation/DSCompiler.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/analysis/differentiation/DerivativeStructureTest.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=1371805&r1=1371804&r2=1371805&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
Fri Aug 10 18:33:06 2012
@@ -1097,10 +1097,39 @@ public class DSCompiler {
         final double x = operand[operandOffset];
         function[0] = FastMath.acos(x);
         if (order > 0) {
-            function[1] = -1.0 / FastMath.sqrt(1 - x * x);
-            for (int i = 2; i <= order; ++i) {
-                // TODO compute higher order derivatives
-                function[i] = Double.NaN;
+            // the nth order derivative of acos has the form:
+            // dn(acos(x)/dxn = P_n(x) / [1 - x^2]^((2n-1)/2)
+            // where P_n(x) is a degree n-1 polynomial with same parity as n-1
+            // P_1(x) = -1, P_2(x) = -x, P_3(x) = -2x^2 - 1 ...
+            // the general recurrence relation for P_n is:
+            // P_n(x) = (1-x^2) P_(n-1)'(x) + (2n-3) x P_(n-1)(x)
+            // 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];
+            p[0] = -1;
+            final double x2    = x * x;
+            final double f     = 1.0 / (1 - x2);
+            double coeff = FastMath.sqrt(f);
+            function[1] = coeff * p[0];
+            for (int n = 2; n <= order; ++n) {
+
+                // update and evaluate polynomial P_n(x)
+                double v = 0;
+                p[n - 1] = (n - 1) * p[n - 2];
+                for (int k = n - 1; k >= 0; k -= 2) {
+                    v = v * x2 + p[k];
+                    if (k > 2) {
+                        p[k - 2] = (k - 1) * p[k - 1] + (2 * n - k) * p[k - 3];
+                    } else if (k == 2) {
+                        p[0] = p[1];
+                    }
+                }
+                if ((n & 0x1) == 0) {
+                    v *= x;
+                }
+
+                coeff *= f;
+                function[n] = coeff * v;
+
             }
         }
 
@@ -1125,10 +1154,39 @@ public class DSCompiler {
         final double x = operand[operandOffset];
         function[0] = FastMath.asin(x);
         if (order > 0) {
-            function[1] = 1.0 / FastMath.sqrt(1 - x * x);
-            for (int i = 2; i <= order; ++i) {
-                // TODO compute higher order derivatives
-                function[i] = Double.NaN;
+            // the nth order derivative of asin has the form:
+            // dn(asin(x)/dxn = P_n(x) / [1 - x^2]^((2n-1)/2)
+            // where P_n(x) is a degree n-1 polynomial with same parity as n-1
+            // P_1(x) = 1, P_2(x) = x, P_3(x) = 2x^2 + 1 ...
+            // the general recurrence relation for P_n is:
+            // P_n(x) = (1-x^2) P_(n-1)'(x) + (2n-3) x P_(n-1)(x)
+            // 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];
+            p[0] = 1;
+            final double x2    = x * x;
+            final double f     = 1.0 / (1 - x2);
+            double coeff = FastMath.sqrt(f);
+            function[1] = coeff * p[0];
+            for (int n = 2; n <= order; ++n) {
+
+                // update and evaluate polynomial P_n(x)
+                double v = 0;
+                p[n - 1] = (n - 1) * p[n - 2];
+                for (int k = n - 1; k >= 0; k -= 2) {
+                    v = v * x2 + p[k];
+                    if (k > 2) {
+                        p[k - 2] = (k - 1) * p[k - 1] + (2 * n - k) * p[k - 3];
+                    } else if (k == 2) {
+                        p[0] = p[1];
+                    }
+                }
+                if ((n & 0x1) == 0) {
+                    v *= x;
+                }
+
+                coeff *= f;
+                function[n] = coeff * v;
+
             }
         }
 
@@ -1153,10 +1211,39 @@ public class DSCompiler {
         final double x = operand[operandOffset];
         function[0] = FastMath.atan(x);
         if (order > 0) {
-            function[1] = 1.0 / (1 + x * x);
-            for (int i = 2; i <= order; ++i) {
-                // TODO compute higher order derivatives
-                function[i] = Double.NaN;
+            // the nth order derivative of atan has the form:
+            // dn(atan(x)/dxn = Q_n(x) / (1 + x^2)^n
+            // where Q_n(x) is a degree n-1 polynomial with same parity as n-1
+            // Q_1(x) = 1, Q_2(x) = -2x, Q_3(x) = 6x^2 - 2 ...
+            // the general recurrence relation for Q_n is:
+            // Q_n(x) = (1+x^2) Q_(n-1)'(x) - 2(n-1) x Q_(n-1)(x)
+            // as per polynomial parity, we can store coefficients of both Q_(n-1) and Q_n
in the same array
+            final double[] q = new double[order];
+            q[0] = 1;
+            final double x2    = x * x;
+            final double f     = 1.0 / (1 + x2);
+            double coeff = f;
+            function[1] = coeff * q[0];
+            for (int n = 2; n <= order; ++n) {
+
+                // update and evaluate polynomial Q_n(x)
+                double v = 0;
+                q[n - 1] = -n * q[n - 2];
+                for (int k = n - 1; k >= 0; k -= 2) {
+                    v = v * x2 + q[k];
+                    if (k > 2) {
+                        q[k - 2] = (k - 1) * q[k - 1] + (k - 1 - 2 * n) * q[k - 3];
+                    } else if (k == 2) {
+                        q[0] = q[1];
+                    }
+                }
+                if ((n & 0x1) == 0) {
+                    v *= x;
+                }
+
+                coeff *= f;
+                function[n] = coeff * v;
+
             }
         }
 

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/analysis/differentiation/DerivativeStructureTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/analysis/differentiation/DerivativeStructureTest.java?rev=1371805&r1=1371804&r2=1371805&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/analysis/differentiation/DerivativeStructureTest.java
(original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/analysis/differentiation/DerivativeStructureTest.java
Fri Aug 10 18:33:06 2012
@@ -460,6 +460,51 @@ public class DerivativeStructureTest {
     }
 
     @Test
+    public void testSinAsin() {
+        double[] epsilon = new double[] { 3.0e-16, 5.0e-16, 3.0e-15, 2.0e-14, 4.0e-13 };
+        for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
+            for (double x = 0.1; x < 1.2; x += 0.001) {
+                DerivativeStructure dsX = new DerivativeStructure(1, maxOrder, 0, x);
+                DerivativeStructure rebuiltX = dsX.sin().asin();
+                DerivativeStructure zero = rebuiltX.subtract(dsX);
+                for (int n = 0; n <= maxOrder; ++n) {
+                    Assert.assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testCosAcos() {
+        double[] epsilon = new double[] { 6.0e-16, 6.0e-15, 2.0e-13, 4.0e-12, 2.0e-10 };
+        for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
+            for (double x = 0.1; x < 1.2; x += 0.001) {
+                DerivativeStructure dsX = new DerivativeStructure(1, maxOrder, 0, x);
+                DerivativeStructure rebuiltX = dsX.cos().acos();
+                DerivativeStructure zero = rebuiltX.subtract(dsX);
+                for (int n = 0; n <= maxOrder; ++n) {
+                    Assert.assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testTanAtan() {
+        double[] epsilon = new double[] { 6.0e-17, 2.0e-16, 2.0e-15, 4.0e-14, 2.0e-12 };
+        for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
+            for (double x = 0.1; x < 1.2; x += 0.001) {
+                DerivativeStructure dsX = new DerivativeStructure(1, maxOrder, 0, x);
+                DerivativeStructure rebuiltX = dsX.tan().atan();
+                DerivativeStructure zero = rebuiltX.subtract(dsX);
+                for (int n = 0; n <= maxOrder; ++n) {
+                    Assert.assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
+                }
+            }
+        }
+    }
+
+    @Test
     public void testTangentDefinition() {
         double[] epsilon = new double[] { 5.0e-16, 2.0e-15, 3.0e-14, 5.0e-13, 2.0e-11 };
         for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {



Mime
View raw message