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.special.elliptic.carlson.CarlsonEllipticIntegral;
20  import org.hipparchus.util.FastMath;
21  import org.hipparchus.util.MathUtils;
22  import org.junit.jupiter.api.Test;
23  
24  import static org.junit.jupiter.api.Assertions.assertEquals;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  class LegendreEllipticIntegralTest {
28  
29      @Test
30      void testNoConvergence() {
31          assertTrue(Double.isNaN(LegendreEllipticIntegral.bigK(Double.NaN)));
32      }
33  
34      @Test
35      void testComplementary() {
36          for (double m = 0.01; m < 1; m += 0.01) {
37              double k1 = LegendreEllipticIntegral.bigK(m);
38              double k2 = LegendreEllipticIntegral.bigKPrime(1 - m);
39              assertEquals(k1, k2, FastMath.ulp(k1));
40          }
41      }
42  
43      @Test
44      void testAbramowitzStegunExample3() {
45          assertEquals(3.591545001,
46                              LegendreEllipticIntegral.bigK(80.0 / 81.0),
47                              2.0e-9);
48      }
49  
50      @Test
51      void testAbramowitzStegunExample4() {
52          assertEquals(1.019106060,
53                              LegendreEllipticIntegral.bigE(80.0 / 81.0),
54                              2.0e-8);
55      }
56  
57      @Test
58      void testAbramowitzStegunExample8() {
59          final double m    = 1.0 / 5.0;
60          final double phi1 = FastMath.acos(FastMath.sqrt(2) / 3.0);
61          final double phi2 = FastMath.acos(FastMath.sqrt(2) / 2.0);
62          assertEquals(1.115921, LegendreEllipticIntegral.bigF(phi1, m), 1.0e-6);
63          assertEquals(0.800380, LegendreEllipticIntegral.bigF(phi2, m), 1.0e-6);
64      }
65  
66      @Test
67      void testAbramowitzStegunExample9() {
68          final double m    = 1.0 / 2.0;
69          final double phi1 = MathUtils.SEMI_PI;
70          final double phi2 = FastMath.PI / 6.0;
71          assertEquals(1.854075, LegendreEllipticIntegral.bigF(phi1, m), 1.0e-6);
72          assertEquals(0.535623, LegendreEllipticIntegral.bigF(phi2, m), 1.0e-6);
73      }
74  
75      @Test
76      void testAbramowitzStegunExample10() {
77          final double m    = 4.0 / 5.0;
78          final double phi  = FastMath.PI / 6.0;
79          assertEquals(0.543604, LegendreEllipticIntegral.bigF(phi, m), 1.0e-6);
80      }
81  
82      @Test
83      void testAbramowitzStegunExample14() {
84          final double k    = 3.0 / 5.0;
85          final double phi1 = FastMath.asin(FastMath.sqrt(5.0) / 3.0);
86          final double phi2 = FastMath.asin(5.0 / (3.0 * FastMath.sqrt(17.0)));
87          assertEquals(0.80904, LegendreEllipticIntegral.bigE(phi1, k * k), 1.0e-5);
88          assertEquals(0.41192, LegendreEllipticIntegral.bigE(phi2, k * k), 1.0e-5);
89      }
90  
91      @Test
92      void testAbramowitzStegunTable175() {
93          final double sinAlpha1 = FastMath.sin(FastMath.toRadians(32));
94          assertEquals(0.26263487,
95                              LegendreEllipticIntegral.bigF(FastMath.toRadians(15), sinAlpha1 * sinAlpha1),
96                              1.0e-8);
97          final double sinAlpha2 = FastMath.sin(FastMath.toRadians(46));
98          assertEquals(1.61923762,
99                              LegendreEllipticIntegral.bigF(FastMath.toRadians(80), sinAlpha2 * sinAlpha2),
100                             1.0e-8);
101     }
102 
103     @Test
104     void testAbramowitzStegunTable176() {
105         final double sinAlpha1 = FastMath.sin(FastMath.toRadians(64));
106         assertEquals(0.42531712,
107                             LegendreEllipticIntegral.bigE(FastMath.toRadians(25), sinAlpha1 * sinAlpha1),
108                             1.0e-8);
109         final double sinAlpha2 = FastMath.sin(FastMath.toRadians(76));
110         assertEquals(0.96208074,
111                             LegendreEllipticIntegral.bigE(FastMath.toRadians(70), sinAlpha2 * sinAlpha2),
112                             1.0e-8);
113     }
114 
115     @Test
116     void testAbramowitzStegunTable179() {
117         final double sinAlpha1 = FastMath.sin(FastMath.toRadians(15));
118         assertEquals(1.62298,
119                             LegendreEllipticIntegral.bigPi(0.4, FastMath.toRadians(75), sinAlpha1 * sinAlpha1),
120                             1.0e-5);
121         final double sinAlpha2 = FastMath.sin(FastMath.toRadians(60));
122         assertEquals(1.03076,
123                             LegendreEllipticIntegral.bigPi(0.8, FastMath.toRadians(45), sinAlpha2 * sinAlpha2),
124                             1.0e-5);
125         final double sinAlpha3 = FastMath.sin(FastMath.toRadians(15));
126         assertEquals(2.79990,
127                             LegendreEllipticIntegral.bigPi(0.9, FastMath.toRadians(75), sinAlpha3 * sinAlpha3),
128                             1.0e-5);
129     }
130 
131     @Test
132     void testCompleteVsIncompleteF() {
133         for (double m = 0.01; m < 1; m += 0.01) {
134             double complete   = LegendreEllipticIntegral.bigK(m);
135             double incomplete = LegendreEllipticIntegral.bigF(MathUtils.SEMI_PI, m);
136             assertEquals(complete, incomplete, FastMath.ulp(complete));
137         }
138     }
139 
140     @Test
141     void testCompleteVsIncompleteE() {
142         for (double m = 0.01; m < 1; m += 0.01) {
143             double complete   = LegendreEllipticIntegral.bigE(m);
144             double incomplete = LegendreEllipticIntegral.bigE(MathUtils.SEMI_PI, m);
145             assertEquals(complete, incomplete, 4 * FastMath.ulp(complete));
146         }
147     }
148 
149     @Test
150     void testCompleteVsIncompleteD() {
151         for (double m = 0.01; m < 1; m += 0.01) {
152             double complete   = LegendreEllipticIntegral.bigD(m);
153             double incomplete = LegendreEllipticIntegral.bigD(MathUtils.SEMI_PI, m);
154             assertEquals(complete, incomplete, FastMath.ulp(complete));
155         }
156     }
157 
158     @Test
159     void testCompleteVsIncompletePi() {
160         for (double alpha2 = 0.01; alpha2 < 1; alpha2 += 0.01) {
161             for (double m = 0.01; m < 1; m += 0.01) {
162                 double complete   = LegendreEllipticIntegral.bigPi(alpha2, m);
163                 double incomplete = LegendreEllipticIntegral.bigPi(alpha2, MathUtils.SEMI_PI, m);
164                 assertEquals(complete, incomplete, FastMath.ulp(complete));
165             }
166         }
167     }
168 
169     @Test
170     void testNomeMediumParameter() {
171         assertEquals(0.0857957337021947665168, LegendreEllipticIntegral.nome(0.75), 1.0e-15);
172     }
173 
174     @Test
175     void testNomeSmallParameter() {
176         assertEquals(5.9375e-18, LegendreEllipticIntegral.nome(0.95e-16), 1.0e-22);
177     }
178 
179     @Test
180     void testIntegralsSmallParameter() {
181         assertEquals(7.8539816428e-10,
182                             LegendreEllipticIntegral.bigK(2.0e-9) - MathUtils.SEMI_PI,
183                             1.0e-15);
184     }
185 
186     @Test
187     void testPrecomputedDelta() {
188 
189         double n   = 0.7;
190         double m   = 0.2;
191         double phi = 1.2;
192         double ref = 1.8264362537906997;
193         assertEquals(ref, LegendreEllipticIntegral.bigPi(n, phi, m), 1.0e-15);
194 
195         // no argument reduction and no precomputed delta
196         final double csc     = 1.0 / FastMath.sin(phi);
197         final double csc2    = csc * csc;
198         final double cM1     = csc2 - 1;
199         final double cMm     = csc2 - m;
200         final double cMn     = csc2 - n;
201         final double pinphim = CarlsonEllipticIntegral.rF(cM1, cMm, csc2) +
202                                CarlsonEllipticIntegral.rJ(cM1, cMm, csc2, cMn) * n / 3;
203         assertEquals(ref, pinphim, 1.0e-15);
204 
205     }
206 
207 }