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