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.special.elliptic.legendre;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.special.elliptic.carlson.CarlsonEllipticIntegral;
22  import org.hipparchus.util.Binary64Field;
23  import org.hipparchus.util.FastMath;
24  import org.hipparchus.util.MathUtils;
25  import org.junit.Assert;
26  import org.junit.Test;
27  
28  public class FieldLegendreEllipticIntegralTest {
29  
30      @Test
31      public void testNoConvergence() {
32          doTestNoConvergence(Binary64Field.getInstance());
33      }
34  
35      private <T extends CalculusFieldElement<T>> void doTestNoConvergence(final Field<T> field) {
36          Assert.assertTrue(LegendreEllipticIntegral.bigK(field.getZero().newInstance(Double.NaN)).isNaN());
37      }
38  
39      @Test
40      public void testComplementary() {
41          doTestComplementary(Binary64Field.getInstance());
42      }
43  
44      private <T extends CalculusFieldElement<T>> void doTestComplementary(final Field<T> field) {
45          for (double m = 0.01; m < 1; m += 0.01) {
46              T k1 = LegendreEllipticIntegral.bigK(field.getZero().newInstance(m));
47              T k2 = LegendreEllipticIntegral.bigKPrime(field.getZero().newInstance(1 - m));
48              Assert.assertEquals(k1.getReal(), k2.getReal(), FastMath.ulp(k1).getReal());
49          }
50      }
51  
52      @Test
53      public void testAbramowitzStegunExample3() {
54          doTestAbramowitzStegunExample3(Binary64Field.getInstance());
55      }
56  
57      private <T extends CalculusFieldElement<T>> void doTestAbramowitzStegunExample3(final Field<T> field) {
58          T k = LegendreEllipticIntegral.bigK(field.getZero().newInstance(80.0 / 81.0));
59          Assert.assertEquals(3.591545001, k.getReal(), 2.0e-9);
60      }
61  
62      public void testAbramowitzStegunExample4() {
63          doTestBigE(Binary64Field.getInstance(), 80.0 / 81.0, 1.019106060, 2.0e-8);
64      }
65  
66      @Test
67      public void testAbramowitzStegunExample8() {
68          final double m    = 1.0 / 5.0;
69          doTestBigF(Binary64Field.getInstance(), FastMath.acos(FastMath.sqrt(2) / 3.0), m, 1.115921, 1.0e-6);
70          doTestBigF(Binary64Field.getInstance(), FastMath.acos(FastMath.sqrt(2) / 2.0), m, 0.800380, 1.0e-6);
71      }
72  
73      @Test
74      public void testAbramowitzStegunExample9() {
75          final double m    = 1.0 / 2.0;
76          doTestBigF(Binary64Field.getInstance(), MathUtils.SEMI_PI, m, 1.854075, 1.0e-6);
77          doTestBigF(Binary64Field.getInstance(), FastMath.PI / 6.0, m, 0.535623, 1.0e-6);
78      }
79  
80      @Test
81      public void testAbramowitzStegunExample10() {
82          final double m    = 4.0 / 5.0;
83          doTestBigF(Binary64Field.getInstance(), FastMath.PI / 6.0, m, 0.543604, 1.0e-6);
84      }
85  
86      @Test
87      public void testAbramowitzStegunExample14() {
88          final double k    = 3.0 / 5.0;
89          doTestBigE(Binary64Field.getInstance(), FastMath.asin(FastMath.sqrt(5.0) / 3.0),          k * k, 0.80904, 1.0e-5);
90          doTestBigE(Binary64Field.getInstance(), FastMath.asin(5.0 / (3.0 * FastMath.sqrt(17.0))), k * k, 0.41192, 1.0e-5);
91      }
92  
93      @Test
94      public void testAbramowitzStegunTable175() {
95          final double sinAlpha1 = FastMath.sin(FastMath.toRadians(32));
96          doTestBigF(Binary64Field.getInstance(), FastMath.toRadians(15), sinAlpha1 * sinAlpha1, 0.26263487, 1.0e-8);
97          final double sinAlpha2 = FastMath.sin(FastMath.toRadians(46));
98          doTestBigF(Binary64Field.getInstance(), FastMath.toRadians(80), sinAlpha2 * sinAlpha2, 1.61923762, 1.0e-8);
99      }
100 
101     @Test
102     public void testAbramowitzStegunTable176() {
103         final double sinAlpha1 = FastMath.sin(FastMath.toRadians(64));
104         doTestBigE(Binary64Field.getInstance(), FastMath.toRadians(25), sinAlpha1 * sinAlpha1, 0.42531712, 1.0e-8);
105         final double sinAlpha2 = FastMath.sin(FastMath.toRadians(76));
106         doTestBigE(Binary64Field.getInstance(), FastMath.toRadians(70), sinAlpha2 * sinAlpha2, 0.96208074, 1.0e-8);
107     }
108 
109     @Test
110     public void testAbramowitzStegunTable179() {
111         final double sinAlpha1 = FastMath.sin(FastMath.toRadians(15));
112         doTestBigPi(Binary64Field.getInstance(), FastMath.toRadians(75), 0.4, sinAlpha1 * sinAlpha1, 1.62298, 1.0e-5);
113         final double sinAlpha2 = FastMath.sin(FastMath.toRadians(60));
114         doTestBigPi(Binary64Field.getInstance(), FastMath.toRadians(45), 0.8, sinAlpha2 * sinAlpha2, 1.03076, 1.0e-5);
115         final double sinAlpha3 = FastMath.sin(FastMath.toRadians(15));
116         doTestBigPi(Binary64Field.getInstance(), FastMath.toRadians(75), 0.9, sinAlpha3 * sinAlpha3, 2.79990, 1.0e-5);
117     }
118 
119     @Test
120     public void testCompleteVsIncompleteF() {
121         doTestCompleteVsIncompleteF(Binary64Field.getInstance());
122     }
123 
124     @Test
125     public void testCompleteVsIncompleteE() {
126         doTestCompleteVsIncompleteE(Binary64Field.getInstance());
127     }
128 
129     @Test
130     public void testCompleteVsIncompleteD() {
131         doTestCompleteVsIncompleteD(Binary64Field.getInstance());
132     }
133 
134     @Test
135     public void testCompleteVsIncompletePi() {
136         doTestCompleteVsIncompletePi(Binary64Field.getInstance());
137     }
138 
139     @Test
140     public void testNomeMediumParameter() {
141         doTestNomeMediumParameter(Binary64Field.getInstance());
142     }
143 
144     @Test
145     public void testNomeSmallParameter() {
146         doTestNomeSmallParameter(Binary64Field.getInstance());
147     }
148 
149     @Test
150     public void testPrecomputedDelta() {
151         doTestPrecomputedDelta(Binary64Field.getInstance());
152     }
153 
154     @Test
155     public void testIntegralsSmallParameter() {
156         doTestIntegralsSmallParameter(Binary64Field.getInstance());
157     }
158 
159     private <T extends CalculusFieldElement<T>> void doTestBigE(final Field<T> field, final double m,
160                                                                 final double expected, final double tol) {
161         Assert.assertEquals(expected,
162                             LegendreEllipticIntegral.bigE(field.getZero().newInstance(m)).getReal(),
163                             tol);
164     }
165 
166     private <T extends CalculusFieldElement<T>> void doTestBigE(final Field<T> field,
167                                                                 final double phi, final double m,
168                                                                 final double expected, final double tol) {
169         Assert.assertEquals(expected,
170                             LegendreEllipticIntegral.bigE(field.getZero().newInstance(phi),
171                                                           field.getZero().newInstance(m)).getReal(),
172                             tol);
173     }
174 
175     private <T extends CalculusFieldElement<T>> void doTestBigF(final Field<T> field,
176                                                                 final double phi, final double m,
177                                                                 final double expected, final double tol) {
178         Assert.assertEquals(expected,
179                             LegendreEllipticIntegral.bigF(field.getZero().newInstance(phi),
180                                                           field.getZero().newInstance(m)).getReal(),
181                             tol);
182     }
183 
184     private <T extends CalculusFieldElement<T>> void doTestBigPi(final Field<T> field,
185                                                                  final double phi, final double alpha2, final double m,
186                                                                  final double expected, final double tol) {
187         Assert.assertEquals(expected,
188                             LegendreEllipticIntegral.bigPi(field.getZero().newInstance(alpha2),
189                                                            field.getZero().newInstance(phi),
190                                                            field.getZero().newInstance(m)).getReal(),
191                             tol);
192     }
193 
194     private <T extends CalculusFieldElement<T>> void doTestCompleteVsIncompleteF(final Field<T> field) {
195         for (double m = 0.01; m < 1; m += 0.01) {
196             double complete   = LegendreEllipticIntegral.bigK(field.getZero().newInstance(m)).getReal();
197             double incomplete = LegendreEllipticIntegral.bigF(field.getZero().newInstance(MathUtils.SEMI_PI),
198                                                               field.getZero().newInstance(m)).getReal();
199             Assert.assertEquals(complete, incomplete, FastMath.ulp(complete));
200         }
201     }
202 
203     private <T extends CalculusFieldElement<T>> void doTestCompleteVsIncompleteE(final Field<T> field) {
204         for (double m = 0.01; m < 1; m += 0.01) {
205             double complete   = LegendreEllipticIntegral.bigE(field.getZero().newInstance(m)).getReal();
206             double incomplete = LegendreEllipticIntegral.bigE(field.getZero().newInstance(MathUtils.SEMI_PI),
207                                                               field.getZero().newInstance(m)).getReal();
208             Assert.assertEquals(complete, incomplete, 4 * FastMath.ulp(complete));
209         }
210     }
211 
212     private <T extends CalculusFieldElement<T>> void doTestCompleteVsIncompleteD(final Field<T> field) {
213         for (double m = 0.01; m < 1; m += 0.01) {
214             double complete   = LegendreEllipticIntegral.bigD(field.getZero().newInstance(m)).getReal();
215             double incomplete = LegendreEllipticIntegral.bigD(field.getZero().newInstance(MathUtils.SEMI_PI),
216                                                               field.getZero().newInstance(m)).getReal();
217             Assert.assertEquals(complete, incomplete, FastMath.ulp(complete));
218         }
219     }
220 
221     private <T extends CalculusFieldElement<T>> void doTestCompleteVsIncompletePi(final Field<T> field) {
222         for (double alpha2 = 0.01; alpha2 < 1; alpha2 += 0.01) {
223             for (double m = 0.01; m < 1; m += 0.01) {
224                 double complete   = LegendreEllipticIntegral.bigPi(field.getZero().newInstance(alpha2),
225                                                                    field.getZero().newInstance(m)).getReal();
226                 double incomplete = LegendreEllipticIntegral.bigPi(field.getZero().newInstance(alpha2),
227                                                                    field.getZero().newInstance(MathUtils.SEMI_PI),
228                                                                    field.getZero().newInstance(m)).getReal();
229                 Assert.assertEquals(complete, incomplete, FastMath.ulp(complete));
230             }
231         }
232     }
233 
234     private <T extends CalculusFieldElement<T>> void doTestNomeMediumParameter(final Field<T> field) {
235         Assert.assertEquals(0.0857957337021947665168, LegendreEllipticIntegral.nome(field.getZero().newInstance(0.75)).getReal(), 1.0e-15);
236     }
237 
238     private <T extends CalculusFieldElement<T>> void doTestNomeSmallParameter(final Field<T> field) {
239         Assert.assertEquals(5.9375e-18, LegendreEllipticIntegral.nome(field.getZero().newInstance(0.95e-16)).getReal(), 1.0e-22);
240     }
241 
242     private <T extends CalculusFieldElement<T>> void doTestIntegralsSmallParameter(final Field<T> field) {
243         Assert.assertEquals(7.8539816428e-10,
244                             LegendreEllipticIntegral.bigK(field.getZero().newInstance(2.0e-9)).getReal() - MathUtils.SEMI_PI,
245                             1.0e-15);
246     }
247 
248     private <T extends CalculusFieldElement<T>> void doTestPrecomputedDelta(final Field<T> field) {
249 
250         T n   = field.getZero().newInstance(0.7);
251         T m   = field.getZero().newInstance(0.2);
252         T phi = field.getZero().newInstance(1.2);
253         T ref = field.getZero().newInstance(1.8264362537906997);
254         Assert.assertEquals(0.0, LegendreEllipticIntegral.bigPi(n, phi, m).subtract(ref).getReal(), 1.0e-15);
255 
256         // no argument reduction and no precomputed delta
257         final T csc     = phi.sin().reciprocal();
258         final T csc2    = csc.multiply(csc);
259         final T cM1     = csc2.subtract(1);
260         final T cMm     = csc2.subtract(m);
261         final T cMn     = csc2.subtract(n);
262         final T pinphim = CarlsonEllipticIntegral.rF(cM1, cMm, csc2).
263                           add(CarlsonEllipticIntegral.rJ(cM1, cMm, csc2, cMn).multiply(n).divide(3));
264         Assert.assertEquals(0.0, pinphim.subtract(ref).getReal(), 1.0e-15);
265 
266     }
267 
268 }