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.differentiation;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.CalculusFieldElementAbstractTest;
21  import org.hipparchus.UnitTestUtils;
22  import org.hipparchus.analysis.FieldUnivariateFunction;
23  import org.hipparchus.exception.LocalizedCoreFormats;
24  import org.hipparchus.exception.MathIllegalArgumentException;
25  import org.hipparchus.util.FastMath;
26  import org.hipparchus.util.FieldSinCos;
27  import org.hipparchus.util.MathArrays;
28  import org.junit.Assert;
29  import org.junit.Test;
30  
31  /**
32   * Test for class {@link UnivariateDerivative}.
33   */
34  public abstract class UnivariateDerivativeAbstractTest<T extends UnivariateDerivative<T>>
35      extends CalculusFieldElementAbstractTest<T> {
36  
37      protected abstract int getMaxOrder();
38  
39      @Override
40      protected abstract T build(final double x);
41  
42      @Test
43      public void testOrder() {
44          Assert.assertEquals(getMaxOrder(), build(0).getOrder());
45      }
46  
47      @Test
48      public void testNewInstance() {
49          T ud = build(5.25);
50          Assert.assertEquals(5.25, ud.getValue(), 1.0e-15);
51          Assert.assertEquals(1.0,  ud.getDerivative(1), 1.0e-15);
52          T newInstance = ud.newInstance(7.5);
53          Assert.assertEquals(7.5, newInstance.getValue(), 1.0e-15);
54          Assert.assertEquals(0.0, newInstance.getDerivative(1), 1.0e-15);
55      }
56  
57      @Test
58      public void testGetPartialDerivative() {
59          try {
60              build(3.0).getPartialDerivative(0, 1);
61              Assert.fail("an exception should have been thrown");
62          } catch( MathIllegalArgumentException miae) {
63              Assert.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
64              Assert.assertEquals(2, ((Integer) miae.getParts()[0]).intValue());
65              Assert.assertEquals(1, ((Integer) miae.getParts()[1]).intValue());
66          }
67      }
68  
69      @Test
70      public void testGetDerivative() {
71          T x  = build(3.0);
72          T ud = x.square();
73          try {
74              ud.getDerivative(-1);
75              Assert.fail("an exception should have been thrown");
76          } catch (MathIllegalArgumentException miae) {
77              Assert.assertEquals(LocalizedCoreFormats.DERIVATION_ORDER_NOT_ALLOWED, miae.getSpecifier());
78          }
79          Assert.assertEquals(9.0, ud.getValue(), 1.0e-15);
80          Assert.assertEquals(9.0, ud.getDerivative(0), 1.0e-15);
81          Assert.assertEquals(6.0, ud.getDerivative(1), 1.0e-15);
82          for (int n = 2; n <= getMaxOrder(); ++n) {
83              Assert.assertEquals(n == 2 ? 2.0 : 0.0, ud.getDerivative(n), 1.0e-15);
84          }
85          try {
86              ud.getDerivative(getMaxOrder() + 1);
87              Assert.fail("an exception should have been thrown");
88          } catch (MathIllegalArgumentException miae) {
89              Assert.assertEquals(LocalizedCoreFormats.DERIVATION_ORDER_NOT_ALLOWED, miae.getSpecifier());
90          }
91      }
92  
93      @Test
94      public void testGetFreeParameters() {
95          Assert.assertEquals(1, build(3.0).getFreeParameters());
96      }
97  
98      protected void checkAgainstDS(final double x, final FieldUnivariateFunction f) {
99          final T xUD = build(x);
100         final T yUD = f.value(xUD);
101         final DerivativeStructure yDS = f.value(xUD.toDerivativeStructure());
102         for (int i = 0; i <= yUD.getOrder(); ++i) {
103             Assert.assertEquals(yDS.getPartialDerivative(i),
104                                 yUD.getDerivative(i),
105                                 4.0e-14* FastMath.abs(yDS.getPartialDerivative(i)));
106         }
107     }
108 
109     @Test
110     public void testArithmeticVsDS() {
111         for (double x = -1.25; x < 1.25; x+= 0.5) {
112             checkAgainstDS(x,
113                            new FieldUnivariateFunction() {
114                                public <S extends CalculusFieldElement<S>> S value(S x) {
115                                    final S y = x.add(3).multiply(x).subtract(5).multiply(0.5);
116                                    return y.negate().divide(4).divide(x).add(y).subtract(x).multiply(2).reciprocal();
117                                }
118                            });
119         }
120     }
121 
122     @Test
123     public void testRemainderDoubleVsDS() {
124         for (double x = -1.25; x < 1.25; x+= 0.5) {
125             checkAgainstDS(x,
126                            new FieldUnivariateFunction() {
127                                public <S extends CalculusFieldElement<S>> S value(S x) {
128                                    return x.remainder(0.5);
129                                }
130                            });
131         }
132     }
133 
134     @Test
135     public void testRemainderUdVsDS() {
136         for (double x = -1.25; x < 1.25; x+= 0.5) {
137             checkAgainstDS(x,
138                            new FieldUnivariateFunction() {
139                               public <S extends CalculusFieldElement<S>> S value(S x) {
140                                   return x.remainder(x.divide(0.7));
141                               }
142                            });
143         }
144     }
145 
146     @Test
147     public void testAbsVsDS() {
148         for (double x = -1.25; x < 1.25; x+= 0.5) {
149             checkAgainstDS(x,
150                            new FieldUnivariateFunction() {
151                                public <S extends CalculusFieldElement<S>> S value(S x) {
152                                    return x.abs();
153                                }
154                            });
155         }
156     }
157 
158     @Test
159     public void testScalbVsDS() {
160         for (int n = -4; n < 4; ++n) {
161             final int theN = n;
162             for (double x = -1.25; x < 1.25; x+= 0.5) {
163                 checkAgainstDS(x,
164                                new FieldUnivariateFunction() {
165                                    public <S extends CalculusFieldElement<S>> S value(S x) {
166                                        return x.scalb(theN);
167                                    }
168                                });
169             }
170         }
171     }
172 
173     @Test
174     public void testUlpVsDS() {
175         for (double x = -1.25; x < 1.25; x+= 0.0001) {
176             checkAgainstDS(x,
177                            new FieldUnivariateFunction() {
178                                public <S extends CalculusFieldElement<S>> S value(S x) {
179                                    return x.ulp();
180                            }
181             });
182         }
183     }
184 
185     @Test
186     public void testHypotVsDS() {
187         for (double x = -3.25; x < 3.25; x+= 0.5) {
188             checkAgainstDS(x,
189                            new FieldUnivariateFunction() {
190                                public <S extends CalculusFieldElement<S>> S value(S x) {
191                                    return x.cos().multiply(5).hypot(x.sin().multiply(2));
192                                }
193                            });
194         }
195     }
196 
197     @Test
198     public void testAtan2VsDS() {
199         for (double x = -3.25; x < 3.25; x+= 0.5) {
200             checkAgainstDS(x,
201                            new FieldUnivariateFunction() {
202                                public <S extends CalculusFieldElement<S>> S value(S x) {
203                                    return x.cos().multiply(5).atan2(x.sin().multiply(2));
204                                }
205                            });
206         }
207     }
208 
209     @Test
210     public void testPowersVsDS() {
211         for (double x = -3.25; x < 3.25; x+= 0.5) {
212             checkAgainstDS(x,
213                            new FieldUnivariateFunction() {
214                                public <S extends CalculusFieldElement<S>> S value(S x) {
215                                    final FieldSinCos<S> sc = x.sinCos();
216                                    return x.pow(3.2).add(x.pow(2)).subtract(sc.cos().abs().pow(sc.sin()));
217                                }
218                            });
219         }
220     }
221 
222     @Test
223     public void testSqrtVsDS() {
224         for (double x = 0.001; x < 3.25; x+= 0.5) {
225             checkAgainstDS(x,
226                     new FieldUnivariateFunction() {
227                         public <S extends CalculusFieldElement<S>> S value(S x) {
228                             return x.sqrt();
229                         }
230                     });
231         }
232     }
233 
234     @Test
235     public void testCbrtVsDS() {
236         for (double x = 0.001; x < 3.25; x+= 0.5) {
237             checkAgainstDS(x,
238                     new FieldUnivariateFunction() {
239                         public <S extends CalculusFieldElement<S>> S value(S x) {
240                             return x.cbrt();
241                         }
242                     });
243         }
244     }
245 
246     @Test
247     public void testRootsVsDS() {
248         for (double x = 0.001; x < 3.25; x+= 0.5) {
249             checkAgainstDS(x,
250                            new FieldUnivariateFunction() {
251                                public <S extends CalculusFieldElement<S>> S value(S x) {
252                                    return x.rootN(5);//x.sqrt().add(x.cbrt()).subtract(x.rootN(5));
253                                }
254                            });
255         }
256     }
257 
258     @Test
259     public void testExpsLogsVsDS() {
260         for (double x = 2.5; x < 3.25; x+= 0.125) {
261             checkAgainstDS(x,
262                            new FieldUnivariateFunction() {
263                                public <S extends CalculusFieldElement<S>> S value(S x) {
264                                    return x.exp().add(x.multiply(0.5).expm1()).log().log10().log1p();
265                                }
266                            });
267         }
268     }
269 
270     @Test
271     public void testTrigonometryVsDS() {
272         for (double x = -3.25; x < 3.25; x+= 0.5) {
273             checkAgainstDS(x,
274                            new FieldUnivariateFunction() {
275                                public <S extends CalculusFieldElement<S>> S value(S x) {
276                                    return x.cos().multiply(x.sin()).atan().divide(12).asin().multiply(0.1).acos().tan();
277                                }
278                            });
279         }
280     }
281 
282     @Test
283     public void testHyperbolicVsDS() {
284         for (double x = -1.25; x < 1.25; x+= 0.5) {
285             checkAgainstDS(x,
286                            new FieldUnivariateFunction() {
287                                public <S extends CalculusFieldElement<S>> S value(S x) {
288                                    return x.cosh().multiply(x.sinh()).multiply(12).abs().acosh().asinh().divide(7).tanh().multiply(0.1).atanh();
289                                }
290                            });
291         }
292     }
293 
294     @Test
295     public void testConvertersVsDS() {
296         for (double x = -1.25; x < 1.25; x+= 0.5) {
297             checkAgainstDS(x,
298                            new FieldUnivariateFunction() {
299                                public <S extends CalculusFieldElement<S>> S value(S x) {
300                                    return x.multiply(5).toDegrees().subtract(x).toRadians();
301                                }
302                            });
303         }
304     }
305 
306     @Test
307     public void testLinearCombination2D2FVsDS() {
308         for (double x = -1.25; x < 1.25; x+= 0.5) {
309             checkAgainstDS(x,
310                            new FieldUnivariateFunction() {
311                                public <S extends CalculusFieldElement<S>> S value(S x) {
312                                    return x.linearCombination(1.0, x.multiply(0.9),
313                                                               2.0, x.multiply(0.8));
314                                }
315                            });
316         }
317     }
318 
319     @Test
320     public void testLinearCombination2F2FVsDS() {
321         for (double x = -1.25; x < 1.25; x+= 0.5) {
322             checkAgainstDS(x,
323                            new FieldUnivariateFunction() {
324                                public <S extends CalculusFieldElement<S>> S value(S x) {
325                                    return x.linearCombination(x.add(1), x.multiply(0.9),
326                                                               x.add(2), x.multiply(0.8));
327                                }
328                            });
329         }
330     }
331 
332     @Test
333     public void testLinearCombination3D3FVsDS() {
334         for (double x = -1.25; x < 1.25; x+= 0.5) {
335             checkAgainstDS(x,
336                            new FieldUnivariateFunction() {
337                                public <S extends CalculusFieldElement<S>> S value(S x) {
338                                    return x.linearCombination(1.0, x.multiply(0.9),
339                                                               2.0, x.multiply(0.8),
340                                                               3.0, x.multiply(0.7));
341                                }
342                            });
343         }
344     }
345 
346     @Test
347     public void testLinearCombination3F3FVsDS() {
348         for (double x = -1.25; x < 1.25; x+= 0.5) {
349             checkAgainstDS(x,
350                            new FieldUnivariateFunction() {
351                                public <S extends CalculusFieldElement<S>> S value(S x) {
352                                    return x.linearCombination(x.add(1), x.multiply(0.9),
353                                                               x.add(2), x.multiply(0.8),
354                                                               x.add(3), x.multiply(0.7));
355                                }
356                            });
357         }
358     }
359 
360     @Test
361     public void testLinearCombination4D4FVsDS() {
362         for (double x = -1.25; x < 1.25; x+= 0.5) {
363             checkAgainstDS(x,
364                            new FieldUnivariateFunction() {
365                                public <S extends CalculusFieldElement<S>> S value(S x) {
366                                    return x.linearCombination(1.0, x.multiply(0.9),
367                                                               2.0, x.multiply(0.8),
368                                                               3.0, x.multiply(0.7),
369                                                               4.0, x.multiply(0.6));
370                                }
371                            });
372         }
373     }
374 
375     @Test
376     public void testLinearCombination4F4FVsDS() {
377         for (double x = -1.25; x < 1.25; x+= 0.5) {
378             checkAgainstDS(x,
379                            new FieldUnivariateFunction() {
380                                public <S extends CalculusFieldElement<S>> S value(S x) {
381                                    return x.linearCombination(x.add(1), x.multiply(0.9),
382                                                               x.add(2), x.multiply(0.8),
383                                                               x.add(3), x.multiply(0.7),
384                                                               x.add(4), x.multiply(0.6));
385                                }
386                            });
387         }
388     }
389 
390     @Test
391     public void testLinearCombinationnDnFVsDS() {
392         for (double x = -1.25; x < 1.25; x+= 0.5) {
393             checkAgainstDS(x,
394                            new FieldUnivariateFunction() {
395                                public <S extends CalculusFieldElement<S>> S value(S x) {
396                                    final S[] b = MathArrays.buildArray(x.getField(), 4);
397                                    b[0] = x.add(0.9);
398                                    b[1] = x.add(0.8);
399                                    b[2] = x.add(0.7);
400                                    b[3] = x.add(0.6);
401                                    return x.linearCombination(new double[] { 1, 2, 3, 4 }, b);
402                                }
403                            });
404         }
405     }
406 
407     @Test
408     public void testLinearCombinationnFnFVsDS() {
409         for (double x = -1.25; x < 1.25; x+= 0.5) {
410             checkAgainstDS(x,
411                            new FieldUnivariateFunction() {
412                                public <S extends CalculusFieldElement<S>> S value(S x) {
413                                    final S[] a = MathArrays.buildArray(x.getField(), 4);
414                                    a[0] = x.add(1);
415                                    a[1] = x.add(2);
416                                    a[2] = x.add(3);
417                                    a[3] = x.add(4);
418                                    final S[] b = MathArrays.buildArray(x.getField(), 4);
419                                    b[0] = x.add(0.9);
420                                    b[1] = x.add(0.8);
421                                    b[2] = x.add(0.7);
422                                    b[3] = x.add(0.6);
423                                    return x.linearCombination(a, b);
424                                }
425                            });
426         }
427     }
428 
429     @Test
430     public void testSerialization() {
431         T a = build(1.3);
432         @SuppressWarnings("unchecked")
433         T b = (T) UnitTestUtils.serializeAndRecover(a);
434         Assert.assertEquals(a, b);
435         Assert.assertNotSame(a, b);
436     }
437 
438     @Test
439     public void testZero() {
440         T zero = build(17.0).getField().getZero();
441         for (int i = 0; i <= zero.getOrder(); ++i) {
442             Assert.assertEquals(0.0, zero.getDerivative(i), 1.0e-15);
443         }
444     }
445 
446     @Test
447     public void testOne() {
448         T one = build(17.0).getField().getOne();
449         for (int i = 0; i <= one.getOrder(); ++i) {
450             Assert.assertEquals(i == 0 ? 1.0 : 0.0, one.getDerivative(i), 1.0e-15);
451         }
452     }
453 
454 }