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