View Javadoc
1   /*
2    * Licensed to the Hipparchus project 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 Hipparchus project 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    *      https://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  package org.hipparchus.analysis.interpolation;
18  
19  import java.util.Arrays;
20  
21  import org.hipparchus.exception.LocalizedCoreFormats;
22  import org.hipparchus.exception.MathIllegalArgumentException;
23  import org.hipparchus.random.RandomGenerator;
24  import org.hipparchus.random.Well1024a;
25  import org.junit.Assert;
26  import org.junit.Test;
27  
28  public class GridAxisTest {
29  
30      @Test
31      public void testLinearAscending() {
32          for (int n = 2; n < 12; ++n) {
33              checkAscending(createLinear(25, n));
34          }
35      }
36  
37      @Test
38      public void testLinearDescending() {
39          for (int n = 2; n < 12; ++n) {
40              checkDescending(createLinear(25, n));
41          }
42      }
43  
44      @Test
45      public void testLinearRandomAccess() {
46          final RandomGenerator random = new Well1024a(0x967ab81207d7b2f4l);
47          for (int n = 2; n < 12; ++n) {
48              checkRandomAccess(random, createLinear(25, n));
49          }
50      }
51  
52      @Test
53      public void testQuadraticAscending() {
54          for (int n = 2; n < 12; ++n) {
55              checkAscending(createQuadratic(25, n));
56          }
57      }
58  
59      @Test
60      public void testQuadraticDescending() {
61          for (int n = 2; n < 12; ++n) {
62              checkDescending(createQuadratic(25, n));
63          }
64      }
65  
66      @Test
67      public void testQuadraticRandomAccess() {
68          final RandomGenerator random = new Well1024a(0x80fc3b30a2da4549l);
69          for (int n = 2; n < 12; ++n) {
70              checkRandomAccess(random, createQuadratic(25, n));
71          }
72      }
73  
74      @Test
75      public void testIrregularAscending() {
76          final RandomGenerator random = new Well1024a(0x66133fa03616fbc9l);
77          for (int n = 2; n < 12; ++n) {
78              checkAscending(createIrregular(random, 25, n));
79          }
80      }
81  
82      @Test
83      public void testIrregularDescending() {
84          final RandomGenerator random = new Well1024a(0x72404bbdc66bc2c7l);
85          for (int n = 2; n < 12; ++n) {
86              checkDescending(createIrregular(random, 25, n));
87          }
88      }
89  
90      @Test
91      public void testIrregularRandomAccess() {
92          final RandomGenerator random = new Well1024a(0x254fbf2a8207e0f6l);
93          for (int n = 2; n < 12; ++n) {
94              checkRandomAccess(random, createIrregular(random, 25, n));
95          }
96      }
97  
98      @Test
99      public void testTooSmallGrid() {
100         try {
101             new GridAxis(new double[3], 4);
102             Assert.fail("an exception should have been thrown");
103         } catch (MathIllegalArgumentException miae) {
104             Assert.assertEquals(LocalizedCoreFormats.INSUFFICIENT_DIMENSION, miae.getSpecifier());
105             Assert.assertEquals(3, ((Integer) miae.getParts()[0]).intValue());
106             Assert.assertEquals(4, ((Integer) miae.getParts()[1]).intValue());
107         }
108     }
109 
110     @Test
111     public void testDuplicate() {
112         try {
113             new GridAxis(new double[] { 0.0, 1.0, 2.0, 2.0, 3.0 }, 2);
114             Assert.fail("an exception should have been thrown");
115         } catch (MathIllegalArgumentException miae) {
116             Assert.assertEquals(LocalizedCoreFormats.NOT_STRICTLY_INCREASING_SEQUENCE, miae.getSpecifier());
117             Assert.assertEquals(2.0, ((Double)  miae.getParts()[0]).doubleValue(), 1.0e-15);
118             Assert.assertEquals(2.0, ((Double)  miae.getParts()[1]).doubleValue(), 1.0e-15);
119             Assert.assertEquals(3,   ((Integer) miae.getParts()[2]).intValue());
120             Assert.assertEquals(2,   ((Integer) miae.getParts()[3]).intValue());
121         }
122     }
123 
124     @Test
125     public void testUnsorted() {
126         try {
127             new GridAxis(new double[] { 0.0, 1.0, 0.5, 2.0, 3.0 }, 2);
128             Assert.fail("an exception should have been thrown");
129         } catch (MathIllegalArgumentException miae) {
130             Assert.assertEquals(LocalizedCoreFormats.NOT_STRICTLY_INCREASING_SEQUENCE, miae.getSpecifier());
131             Assert.assertEquals(0.5, ((Double)  miae.getParts()[0]).doubleValue(), 1.0e-15);
132             Assert.assertEquals(1.0, ((Double)  miae.getParts()[1]).doubleValue(), 1.0e-15);
133             Assert.assertEquals(2,   ((Integer) miae.getParts()[2]).intValue());
134             Assert.assertEquals(1,   ((Integer) miae.getParts()[3]).intValue());
135         }
136     }
137 
138     private GridAxis createLinear(final int size, final int n) {
139         final double[] gridData = new double[size];
140         for (int i = 0; i < size; ++i) {
141             gridData[i] = 2 * i + 0.5;
142         }
143         return create(gridData, n);
144     }
145 
146     private GridAxis createQuadratic(final int size, final int n) {
147         final double[] gridData = new double[size];
148         for (int i = 0; i < size; ++i) {
149             gridData[i] = (i + 0.5) * (i + 3);
150         }
151         return create(gridData, n);
152     }
153 
154     private GridAxis createIrregular(final RandomGenerator random, final int size, final int n) {
155         final double[] gridData = new double[size];
156         for (int i = 0; i < size; ++i) {
157             gridData[i] = 50.0 * random.nextDouble();
158         }
159         Arrays.sort(gridData);
160         return create(gridData, n);
161     }
162 
163     private GridAxis create(final double[] gridData, final int n) {
164         final GridAxis gridAxis = new GridAxis(gridData, n);
165         Assert.assertEquals(n, gridAxis.getN());
166         for (int i = 0; i < 5; ++i) {
167             Assert.assertEquals(gridData[i], gridAxis.node(i), 1.0e-15);
168         }
169         return gridAxis;
170     }
171 
172     private void checkAscending(final GridAxis gridAxis) {
173         final double inf = gridAxis.node(0) - 2.0;
174         final double sup = gridAxis.node(gridAxis.size() - 1) + 2.0;
175         for (double t = inf; t < sup; t += 0.125) {
176             checkInterpolation(t, gridAxis);
177         }
178     }
179 
180     private void checkDescending(final GridAxis gridAxis) {
181         final double inf = gridAxis.node(0) - 2.0;
182         final double sup = gridAxis.node(gridAxis.size() - 1) + 2.0;
183         for (double t = sup; t > inf; t -= 0.125) {
184             checkInterpolation(t, gridAxis);
185         }
186     }
187 
188     private void checkRandomAccess(final RandomGenerator random, final GridAxis gridAxis) {
189         final double inf = gridAxis.node(0) - 2.0;
190         final double sup = gridAxis.node(gridAxis.size() - 1) + 2.0;
191         for (int i = 0; i < 1000; ++i) {
192             checkInterpolation(inf + random.nextDouble() * (sup - inf), gridAxis);
193         }
194     }
195 
196     private void checkInterpolation(final double t, final GridAxis gridAxis) {
197         final int s = gridAxis.size();
198         final int n = gridAxis.getN();
199         final int o = (n - 1) / 2;
200         final int p = n / 2;
201         final int i = gridAxis.interpolationIndex(t);
202         Assert.assertTrue(i >= 0);
203         Assert.assertTrue(i + n - 1 < s);
204         if (t < gridAxis.node(0)) {
205             // extrapolating below grid
206             Assert.assertEquals(0, i);
207         } else if (t < gridAxis.node(s - 1)) {
208 
209             // interpolating within the grid
210             // the nodes should surround the test value
211             Assert.assertTrue(gridAxis.node(i) <= t);
212             Assert.assertTrue(gridAxis.node(i + n - 1) > t);
213 
214             if (t >= gridAxis.node(o) && t <  gridAxis.node(s - p)) {
215                 // interpolation in the part of the grid where balancing is possible
216                 // the central nodes should surround the test value
217                 Assert.assertTrue(gridAxis.node(i + o)     <= t);
218                 Assert.assertTrue(gridAxis.node(i + o + 1) >  t);
219             }
220 
221         } else {
222             // extrapolating above grid
223             Assert.assertEquals(s - n, i);
224         }
225     }
226 
227 }