View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math4.legacy.analysis.differentiation;
19  
20  import org.apache.commons.math4.legacy.TestUtils;
21  import org.apache.commons.math4.core.jdkmath.JdkMath;
22  import org.junit.Assert;
23  import org.junit.Test;
24  
25  
26  /**
27   * Test for class {@link JacobianFunction}.
28   */
29  public class JacobianFunctionTest {
30  
31      @Test
32      public void testSphere() {
33          SphereMapping    f = new SphereMapping(10.0);
34          JacobianFunction j = new JacobianFunction(f);
35          for (double latitude = -1.5; latitude < 1.5; latitude += 0.1) {
36              for (double longitude = -3.1; longitude < 3.1; longitude += 0.1) {
37                  double[] point = new double[] { latitude, longitude };
38                  double[][] referenceJacobian  = f.jacobian(point);
39                  double[][] testJacobian       = j.value(point);
40                  Assert.assertEquals(referenceJacobian.length, testJacobian.length);
41                  for (int i = 0; i < 3; ++i) {
42                      TestUtils.assertEquals(referenceJacobian[i], testJacobian[i], 2.0e-15);
43                  }
44              }
45          }
46      }
47  
48      /* Maps (latitude, longitude) to (x, y, z) */
49      private static final class SphereMapping implements MultivariateDifferentiableVectorFunction {
50  
51          private final double radius;
52  
53          SphereMapping(final double radius) {
54              this.radius = radius;
55          }
56  
57          @Override
58          public double[] value(double[] point) {
59              final double cLat = JdkMath.cos(point[0]);
60              final double sLat = JdkMath.sin(point[0]);
61              final double cLon = JdkMath.cos(point[1]);
62              final double sLon = JdkMath.sin(point[1]);
63              return new double[] {
64                  radius * cLon * cLat,
65                  radius * sLon * cLat,
66                  radius * sLat
67              };
68          }
69  
70          @Override
71          public DerivativeStructure[] value(DerivativeStructure[] point) {
72              final DerivativeStructure cLat = point[0].cos();
73              final DerivativeStructure sLat = point[0].sin();
74              final DerivativeStructure cLon = point[1].cos();
75              final DerivativeStructure sLon = point[1].sin();
76              return new DerivativeStructure[] {
77                  cLon.multiply(cLat).multiply(radius),
78                  sLon.multiply(cLat).multiply(radius),
79                  sLat.multiply(radius)
80              };
81          }
82  
83          public double[][] jacobian(double[] point) {
84              final double cLat = JdkMath.cos(point[0]);
85              final double sLat = JdkMath.sin(point[0]);
86              final double cLon = JdkMath.cos(point[1]);
87              final double sLon = JdkMath.sin(point[1]);
88              return new double[][] {
89                  { -radius * cLon * sLat, -radius * sLon * cLat },
90                  { -radius * sLon * sLat,  radius * cLon * cLat },
91                  {  radius * cLat,         0  }
92              };
93          }
94      }
95  }