1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.special.elliptic.jacobi;
18
19 import org.hipparchus.analysis.UnivariateFunction;
20 import org.hipparchus.util.FastMath;
21 import org.junit.jupiter.api.Test;
22
23 import static org.junit.jupiter.api.Assertions.assertEquals;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25
26 class JacobiEllipticTest {
27
28 @Test
29 void testCircular() {
30 for (double m : new double[] { -1.0e-10, 0.0, 1.0e-10 }) {
31 final double eps = 3 * FastMath.max(1.0e-14, FastMath.abs(m));
32 final JacobiElliptic je = JacobiEllipticBuilder.build(m);
33 for (double t = -10; t < 10; t += 0.01) {
34 final CopolarN n = je.valuesN(t);
35 assertEquals(FastMath.sin(t), n.sn(), eps);
36 assertEquals(FastMath.cos(t), n.cn(), eps);
37 assertEquals(1.0, n.dn(), eps);
38 }
39 }
40 }
41
42 @Test
43 void testHyperbolic() {
44 for (double m1 : new double[] { -1.0e-12, 0.0, 1.0e-12 }) {
45 final double eps = 3 * FastMath.max(1.0e-14, FastMath.abs(m1));
46 final JacobiElliptic je = JacobiEllipticBuilder.build(1.0 - m1);
47 for (double t = -3; t < 3; t += 0.01) {
48 final CopolarN n = je.valuesN(t);
49 assertEquals(FastMath.tanh(t), n.sn(), eps);
50 assertEquals(1.0 / FastMath.cosh(t), n.cn(), eps);
51 assertEquals(1.0 / FastMath.cosh(t), n.dn(), eps);
52 }
53 }
54 }
55
56 @Test
57 void testNoConvergence() {
58 assertTrue(Double.isNaN(JacobiEllipticBuilder.build(Double.NaN).valuesS(0.0).cs()));
59 }
60
61 @Test
62 void testNegativeParameter() {
63 assertEquals(0.49781366219021166315, JacobiEllipticBuilder.build(-4.5).valuesN(8.3).sn(), 1.5e-10);
64 assertEquals(0.86728401215332559984, JacobiEllipticBuilder.build(-4.5).valuesN(8.3).cn(), 1.5e-10);
65 assertEquals(1.45436686918553524215, JacobiEllipticBuilder.build(-4.5).valuesN(8.3).dn(), 1.5e-10);
66 }
67
68 @Test
69 void testAbramowitzStegunExample1() {
70
71 assertEquals(-1392.11114434139393839735, JacobiEllipticBuilder.build(0.64).valuesC(1.99650).nc(), 6.0e-10);
72 }
73
74 @Test
75 void testAbramowitzStegunExample2() {
76 assertEquals(0.996253, JacobiEllipticBuilder.build(0.19).valuesN(0.20).dn(), 1.0e-6);
77 }
78
79 @Test
80 void testAbramowitzStegunExample3() {
81 assertEquals(0.984056, JacobiEllipticBuilder.build(0.81).valuesN(0.20).dn(), 1.0e-6);
82 }
83
84 @Test
85 void testAbramowitzStegunExample4() {
86 assertEquals(0.980278, JacobiEllipticBuilder.build(0.81).valuesN(0.20).cn(), 1.0e-6);
87 }
88
89 @Test
90 void testAbramowitzStegunExample5() {
91 assertEquals(0.60952, JacobiEllipticBuilder.build(0.36).valuesN(0.672).sn(), 1.0e-5);
92 assertEquals(1.1740, JacobiEllipticBuilder.build(0.36).valuesC(0.672).dc(), 1.0e-4);
93 }
94
95 @Test
96 void testAbramowitzStegunExample7() {
97 assertEquals(1.6918083, JacobiEllipticBuilder.build(0.09).valuesS(0.5360162).cs(), 1.0e-7);
98 }
99
100 @Test
101 void testAbramowitzStegunExample8() {
102 assertEquals(0.56458, JacobiEllipticBuilder.build(0.5).valuesN(0.61802).sn(), 1.0e-5);
103 }
104
105 @Test
106 void testAbramowitzStegunExample9() {
107 assertEquals(0.68402, JacobiEllipticBuilder.build(0.5).valuesC(0.61802).sc(), 1.0e-5);
108 }
109
110 @Test
111 void testAllFunctions() {
112
113
114
115
116 final double u = 1.4;
117 final double m = 0.7;
118 final double[] reference = {
119 0.92516138673582827365, 0.37957398289798418747, 0.63312991237590996850,
120 0.41027866958131945027, 0.68434537093007175683, 1.08089249544689572795,
121 1.66800134071905681841, 2.63453251554589286796, 2.43736775548306830513,
122 1.57945467502452678756, 1.46125047743207819361, 0.59951990180590090343
123 };
124 final JacobiElliptic je = JacobiEllipticBuilder.build(m);
125 assertEquals(reference[ 0], je.valuesN(u).sn(), 4 * FastMath.ulp(reference[ 0]));
126 assertEquals(reference[ 1], je.valuesN(u).cn(), 4 * FastMath.ulp(reference[ 1]));
127 assertEquals(reference[ 2], je.valuesN(u).dn(), 4 * FastMath.ulp(reference[ 2]));
128 assertEquals(reference[ 3], je.valuesS(u).cs(), 4 * FastMath.ulp(reference[ 3]));
129 assertEquals(reference[ 4], je.valuesS(u).ds(), 4 * FastMath.ulp(reference[ 4]));
130 assertEquals(reference[ 5], je.valuesS(u).ns(), 4 * FastMath.ulp(reference[ 5]));
131 assertEquals(reference[ 6], je.valuesC(u).dc(), 4 * FastMath.ulp(reference[ 6]));
132 assertEquals(reference[ 7], je.valuesC(u).nc(), 4 * FastMath.ulp(reference[ 7]));
133 assertEquals(reference[ 8], je.valuesC(u).sc(), 4 * FastMath.ulp(reference[ 8]));
134 assertEquals(reference[ 9], je.valuesD(u).nd(), 4 * FastMath.ulp(reference[ 9]));
135 assertEquals(reference[10], je.valuesD(u).sd(), 4 * FastMath.ulp(reference[10]));
136 assertEquals(reference[11], je.valuesD(u).cd(), 4 * FastMath.ulp(reference[11]));
137 }
138
139 @Test
140 void testInverseCopolarN() {
141 final double m = 0.7;
142 final JacobiElliptic je = JacobiEllipticBuilder.build(m);
143 doTestInverse(-0.80, 0.80, 100, u -> je.valuesN(u).sn(), x -> je.arcsn(x), 1.0e-14);
144 doTestInverse(-1.00, 1.00, 100, u -> je.valuesN(u).cn(), x -> je.arccn(x), 1.0e-14);
145 doTestInverse( 0.55, 1.00, 100, u -> je.valuesN(u).dn(), x -> je.arcdn(x), 1.0e-14);
146 }
147
148 @Test
149 void testInverseCopolarS() {
150 final double m = 0.7;
151 final JacobiElliptic je = JacobiEllipticBuilder.build(m);
152 doTestInverse(-2.00, 2.00, 100, u -> je.valuesS(u).cs(), x -> je.arccs(x), 1.0e-14);
153 doTestInverse( 0.55, 2.00, 100, u -> je.valuesS(u).ds(), x -> je.arcds(x), 1.0e-14);
154 doTestInverse(-2.00, -0.55, 100, u -> je.valuesS(u).ds(), x -> je.arcds(x), 1.0e-14);
155 doTestInverse( 1.00, 2.00, 100, u -> je.valuesS(u).ns(), x -> je.arcns(x), 1.0e-11);
156 doTestInverse(-2.00, -1.00, 100, u -> je.valuesS(u).ns(), x -> je.arcns(x), 1.0e-11);
157 }
158
159 @Test
160 void testInverseCopolarC() {
161 final double m = 0.7;
162 final JacobiElliptic je = JacobiEllipticBuilder.build(m);
163 doTestInverse( 1.00, 2.00, 100, u -> je.valuesC(u).dc(), x -> je.arcdc(x), 1.0e-14);
164 doTestInverse(-2.00, -1.00, 100, u -> je.valuesC(u).dc(), x -> je.arcdc(x), 1.0e-14);
165 doTestInverse( 1.00, 2.00, 100, u -> je.valuesC(u).nc(), x -> je.arcnc(x), 1.0e-14);
166 doTestInverse(-2.00, -1.00, 100, u -> je.valuesC(u).nc(), x -> je.arcnc(x), 1.0e-14);
167 doTestInverse(-2.00, 2.00, 100, u -> je.valuesC(u).sc(), x -> je.arcsc(x), 1.0e-14);
168 }
169
170 @Test
171 void testInverseCopolarD() {
172 final double m = 0.7;
173 final JacobiElliptic je = JacobiEllipticBuilder.build(m);
174 doTestInverse( 1.00, 1.80, 100, u -> je.valuesD(u).nd(), x -> je.arcnd(x), 1.0e-14);
175 doTestInverse(-1.80, 1.80, 100, u -> je.valuesD(u).sd(), x -> je.arcsd(x), 1.0e-14);
176 doTestInverse(-1.00, 1.00, 100, u -> je.valuesD(u).cd(), x -> je.arccd(x), 1.0e-14);
177 }
178
179 private void doTestInverse(final double xMin, final double xMax, final int n,
180 final UnivariateFunction direct, final UnivariateFunction inverse,
181 final double tolerance) {
182 for (int i = 0; i < n; ++i) {
183 final double x = xMin + i * (xMax - xMin) / (n - 1);
184 final double xRebuilt = direct.value(inverse.value(x));
185 assertEquals(x, xRebuilt, tolerance);
186 }
187 }
188
189 }