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 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    *      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.function;
18  
19  import java.lang.reflect.InvocationTargetException;
20  import java.lang.reflect.Method;
21  
22  import org.hipparchus.CalculusFieldElement;
23  import org.hipparchus.analysis.UnivariateFunction;
24  import org.hipparchus.analysis.differentiation.DSFactory;
25  import org.hipparchus.analysis.differentiation.DerivativeStructure;
26  import org.hipparchus.analysis.differentiation.Gradient;
27  import org.hipparchus.analysis.differentiation.UnivariateDifferentiableFunction;
28  import org.hipparchus.util.FastMath;
29  import org.junit.Assert;
30  import org.junit.Test;
31  
32  public class FunctionsWithFastMathVersionTest {
33  
34      @Test
35      public void testAcos() {
36          doTestF0(new Acos(), -1.25, -0.25, 0.0, 0.25, 1.25);
37          doTestFn(new Acos(), -1.25, -0.25, 0.0, 0.25, 1.25);
38          doTestF1(new Acos(), -1.25, -0.25, 0.0, 0.25, 1.25);
39      }
40  
41      @Test
42      public void testAcosH() {
43          doTestF0(new Acosh(), -10.0, -5.0, -0.5, 0.5, 5.0, 10.0);
44          doTestFn(new Acosh(), -10.0, -5.0, -0.5, 0.5, 5.0, 10.0);
45          doTestF1(new Acosh(), -10.0, -5.0, -0.5, 0.5, 5.0, 10.0);
46      }
47  
48      @Test
49      public void testAsin() {
50          doTestF0(new Asin(), -1.25, -0.25, 0.0, 0.25, 1.25);
51          doTestFn(new Asin(), -1.25, -0.25, 0.0, 0.25, 1.25);
52          doTestF1(new Asin(), -1.25, -0.25, 0.0, 0.25, 1.25);
53      }
54  
55      @Test
56      public void testAsinh() {
57          doTestF0(new Asinh(), -10.0, -1.25, 0.0, 1.25, 10.0);
58          doTestFn(new Asinh(), -10.0, -1.25, 0.0, 1.25, 10.0);
59          doTestF1(new Asinh(), -10.0, -1.25, 0.0, 1.25, 10.0);
60      }
61  
62      @Test
63      public void testAtan() {
64          doTestF0(new Atan(), -10.0, -1.25, 0.0, 1.25, 10.0);
65          doTestFn(new Atan(), -10.0, -1.25, 0.0, 1.25, 10.0);
66          doTestF1(new Atan(), -10.0, -1.25, 0.0, 1.25, 10.0);
67      }
68  
69      @Test
70      public void testAtanh() {
71          doTestF0(new Atanh(), -10.0, -1.25, 0.0, 1.25, 10.0);
72          doTestFn(new Atanh(), -10.0, -1.25, 0.0, 1.25, 10.0);
73          doTestF1(new Atanh(), -10.0, -1.25, 0.0, 1.25, 10.0);
74      }
75  
76      @Test
77      public void testCbrt() {
78          doTestF0(new Cbrt(), -10.0, -1.25, 0.0, 1.25, 10.0);
79          doTestFn(new Cbrt(), -10.0, -1.25, 0.0, 1.25, 10.0);
80          doTestF1(new Cbrt(), -10.0, -1.25, 0.0, 1.25, 10.0);
81      }
82  
83      @Test
84      public void testCeil() {
85          doTestF0(new Ceil(), -10.0, -1.25, 0.0, 1.25, 10.0);
86          doTestFn(new Ceil(), -10.0, -1.25, 0.0, 1.25, 10.0);
87          doTestF1(new Ceil(), -10.0, -1.25, 0.0, 1.25, 10.0);
88      }
89  
90      @Test
91      public void testCos() {
92          doTestF0(new Cos(), -10.0, -1.25, 0.0, 1.25, 10.0);
93          doTestFn(new Cos(), -10.0, -1.25, 0.0, 1.25, 10.0);
94          doTestF1(new Cos(), -10.0, -1.25, 0.0, 1.25, 10.0);
95      }
96  
97      @Test
98      public void testCosh() {
99          doTestF0(new Cosh(), -10.0, -1.25, -0.5, 0.0, 0.5, 1.25, 10.0);
100         doTestFn(new Cosh(), -10.0, -1.25, -0.5, 0.0, 0.5, 1.25, 10.0);
101         doTestF1(new Cosh(), -10.0, -1.25, -0.5, 0.0, 0.5, 1.25, 10.0);
102     }
103 
104     @Test
105     public void testExp() {
106         doTestF0(new Exp(), -10.0, -1.25, 0.0, 1.25, 10.0);
107         doTestFn(new Exp(), -10.0, -1.25, 0.0, 1.25, 10.0);
108         doTestF1(new Exp(), -10.0, -1.25, 0.0, 1.25, 10.0);
109     }
110 
111     @Test
112     public void testExpm1() {
113         doTestF0(new Expm1(), -10.0, -1.25, 0.0, 1.25, 10.0);
114         doTestFn(new Expm1(), -10.0, -1.25, 0.0, 1.25, 10.0);
115         doTestF1(new Expm1(), -10.0, -1.25, 0.0, 1.25, 10.0);
116     }
117 
118     @Test
119     public void testFloor() {
120         doTestF0(new Floor(), -10.0, -1.25, 0.0, 1.25, 10.0);
121         doTestFn(new Floor(), -10.0, -1.25, 0.0, 1.25, 10.0);
122         doTestF1(new Floor(), -10.0, -1.25, 0.0, 1.25, 10.0);
123     }
124 
125     @Test
126     public void testLog() {
127         doTestF0(new Log(), -10.0, -1.25, 0.0, 1.25, 10.0);
128         doTestFn(new Log(), -10.0, -1.25, 0.0, 1.25, 10.0);
129         doTestF1(new Log(), -10.0, -1.25, 0.0, 1.25, 10.0);
130     }
131 
132     @Test
133     public void testLog10() {
134         doTestF0(new Log10(), -10.0, -1.25, 0.0, 1.25, 10.0);
135         doTestFn(new Log10(), -10.0, -1.25, 0.0, 1.25, 10.0);
136         doTestF1(new Log10(), -10.0, -1.25, 0.0, 1.25, 10.0);
137     }
138 
139     @Test
140     public void testLog1p() {
141         doTestF0(new Log1p(), -10.0, -1.25, 0.0, 1.25, 10.0);
142         doTestFn(new Log1p(), -10.0, -1.25, 0.0, 1.25, 10.0);
143         doTestF1(new Log1p(), -10.0, -1.25, 0.0, 1.25, 10.0);
144     }
145 
146     @Test
147     public void testRint() {
148         doTestF0(new Rint(), -10.0, -1.25, 0.0, 1.25, 10.0);
149         doTestFn(new Rint(), -10.0, -1.25, 0.0, 1.25, 10.0);
150         doTestF1(new Rint(), -10.0, -1.25, 0.0, 1.25, 10.0);
151     }
152 
153     @Test
154     public void testSin() {
155         doTestF0(new Sin(), -10.0, -1.25, 0.0, 1.25, 10.0);
156         doTestFn(new Sin(), -10.0, -1.25, 0.0, 1.25, 10.0);
157         doTestF1(new Sin(), -10.0, -1.25, 0.0, 1.25, 10.0);
158     }
159 
160     @Test
161     public void testSinh() {
162         doTestF0(new Sinh(), -10.0, -1.25, 0.0, 1.25, 10.0);
163         doTestFn(new Sinh(), -10.0, -1.25, 0.0, 1.25, 10.0);
164         doTestF1(new Sinh(), -10.0, -1.25, 0.0, 1.25, 10.0);
165     }
166 
167     @Test
168     public void testSqrt() {
169         doTestF0(new Sqrt(), -10.0, -1.25, 0.0, 1.25, 10.0);
170         doTestFn(new Sqrt(), -10.0, -1.25, 0.0, 1.25, 10.0);
171         doTestF1(new Sqrt(), -10.0, -1.25, 0.0, 1.25, 10.0);
172     }
173 
174     @Test
175     public void testTan() {
176         doTestF0(new Tan(), -10.0, -1.25, 0.0, 1.25, 10.0);
177         doTestFn(new Tan(), -10.0, -1.25, 0.0, 1.25, 10.0);
178         doTestF1(new Tan(), -10.0, -1.25, 0.0, 1.25, 10.0);
179     }
180 
181     @Test
182     public void testTanh() {
183         doTestF0(new Tanh(), -10.0, -1.25, 0.0, 1.25, 10.0);
184         doTestFn(new Tanh(), -10.0, -1.25, 0.0, 1.25, 10.0);
185         doTestF1(new Tanh(), -10.0, -1.25, 0.0, 1.25, 10.0);
186     }
187 
188     @Test
189     public void testUlp() {
190         doTestF0(new Ulp(), -10.0, -1.25, 0.0, 1.25, 10.0);
191     }
192 
193     @Test
194     public void testAtan2() {
195         final double[] d = { Double.NEGATIVE_INFINITY, -13.4, -0.4, 0.0, 0.4, 13.4, Double.POSITIVE_INFINITY, Double.NaN};
196         for (double x : d) {
197             for (double y : d) {
198                 double aRef = FastMath.atan2(y, x);
199                 double a    = new Atan2().value(y, x);
200                 if (Double.isNaN(aRef)) {
201                     Assert.assertTrue(Double.isNaN(a));
202                 } else if (Double.isInfinite(aRef)) {
203                     Assert.assertTrue(Double.isInfinite(a));
204                     Assert.assertTrue(a * aRef > 0.0);
205                 } else {
206                     Assert.assertEquals(aRef, a, FastMath.ulp(aRef));
207                 }
208             }
209         }
210     }
211 
212     private void doTestF0(final UnivariateFunction f, double... x) {
213         try {
214             final Method fastMathVersion = FastMath.class.getMethod(f.getClass().getSimpleName().toLowerCase(), Double.TYPE);
215             for (double xi : x) {
216                 checkF0Equality(f, fastMathVersion, xi);
217             }
218             checkF0Equality(f, fastMathVersion, Double.NEGATIVE_INFINITY);
219             checkF0Equality(f, fastMathVersion, Double.POSITIVE_INFINITY);
220             checkF0Equality(f, fastMathVersion, Double.NaN);
221         } catch (NoSuchMethodException e) {
222             Assert.fail(e.getLocalizedMessage());
223         }
224     }
225 
226     private void checkF0Equality(final UnivariateFunction f, final Method ref, final double x) {
227         try {
228             double yRef = ((Double) ref.invoke(null, x)).doubleValue();
229             double y    = f.value(x);
230             if (Double.isNaN(yRef)) {
231                 Assert.assertTrue(Double.isNaN(y));
232             } else if (Double.isInfinite(yRef)) {
233                 Assert.assertTrue(Double.isInfinite(y));
234                 Assert.assertTrue(y * yRef > 0.0);
235             } else {
236                 Assert.assertEquals(yRef, y, FastMath.ulp(yRef));
237             }
238         } catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
239             Assert.fail(e.getLocalizedMessage());
240         }
241     }
242 
243     private void doTestFn(final UnivariateDifferentiableFunction f, double... x) {
244         try {
245             final Method fastMathVersion = FastMath.class.getMethod(f.getClass().getSimpleName().toLowerCase(),
246                                                                     CalculusFieldElement.class);
247             for (double xi : x) {
248                 checkFnEqualities(f, fastMathVersion, xi);
249             }
250             checkFnEqualities(f, fastMathVersion, Double.NEGATIVE_INFINITY);
251             checkFnEqualities(f, fastMathVersion, Double.POSITIVE_INFINITY);
252             checkFnEqualities(f, fastMathVersion, Double.NaN);
253         } catch (NoSuchMethodException e) {
254             Assert.fail(e.getLocalizedMessage());
255         }
256     }
257 
258     private void checkFnEqualities(final UnivariateDifferentiableFunction f, final Method ref, final double x) {
259         try {
260             DSFactory           factory = new DSFactory(1, 5);
261             DerivativeStructure xDS     = factory.variable(0, x);
262             DerivativeStructure yRef    = (DerivativeStructure) ref.invoke(null, xDS);
263             DerivativeStructure y       = f.value(xDS);
264             for (int order = 0; order < factory.getCompiler().getOrder(); ++order) {
265                 if (Double.isNaN(yRef.getPartialDerivative(order))) {
266                     Assert.assertTrue(Double.isNaN(y.getPartialDerivative(order)));
267                 } else if (Double.isInfinite(yRef.getPartialDerivative(order))) {
268                     Assert.assertTrue(Double.isInfinite(y.getPartialDerivative(order)));
269                     Assert.assertTrue(y.getPartialDerivative(order) * yRef.getPartialDerivative(order) > 0.0);
270                 } else {
271                     Assert.assertEquals(yRef.getPartialDerivative(order), y.getPartialDerivative(order), FastMath.ulp(yRef.getPartialDerivative(order)));
272                 }
273             }
274         } catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
275             Assert.fail(e.getLocalizedMessage());
276         }
277     }
278 
279     private void doTestF1(final UnivariateDifferentiableFunction f, double... x) {
280         try {
281             final Method fastMathVersion = FastMath.class.getMethod(f.getClass().getSimpleName().toLowerCase(),
282                                                                     CalculusFieldElement.class);
283             for (double xi : x) {
284                 checkF1Equalities(f, fastMathVersion, xi);
285             }
286             checkF1Equalities(f, fastMathVersion, Double.NEGATIVE_INFINITY);
287             checkF1Equalities(f, fastMathVersion, Double.POSITIVE_INFINITY);
288             checkF1Equalities(f, fastMathVersion, Double.NaN);
289         } catch (NoSuchMethodException e) {
290             Assert.fail(e.getLocalizedMessage());
291         }
292     }
293 
294     private void checkF1Equalities(final UnivariateDifferentiableFunction f, final Method ref, final double x) {
295         try {
296             Gradient xDS     = Gradient.variable(1, 0, x);
297             Gradient yRef    = (Gradient) ref.invoke(null, xDS);
298             Gradient y       = f.value(xDS);
299             if (Double.isNaN(yRef.getPartialDerivative(0))) {
300                 Assert.assertTrue(Double.isNaN(y.getPartialDerivative(0)));
301             } else if (Double.isInfinite(yRef.getPartialDerivative(0))) {
302                 Assert.assertTrue(Double.isInfinite(y.getPartialDerivative(0)));
303                 Assert.assertTrue(y.getPartialDerivative(0) * yRef.getPartialDerivative(0) > 0.0);
304             } else {
305                 Assert.assertEquals(yRef.getPartialDerivative(0), y.getPartialDerivative(0), FastMath.ulp(yRef.getPartialDerivative(0)));
306             }
307         } catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
308             Assert.fail(e.getLocalizedMessage());
309         }
310     }
311 
312 }