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.jacobi;
18  
19  import java.io.IOException;
20  
21  import org.hipparchus.UnitTestUtils;
22  import org.hipparchus.complex.Complex;
23  import org.hipparchus.special.elliptic.legendre.LegendreEllipticIntegral;
24  import org.junit.Test;
25  
26  public class JacobiEllipticComplexTest {
27  
28      @Test
29      public void testComplex() throws IOException {
30          final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 1.0));
31          UnitTestUtils.assertEquals(Complex.valueOf(-0.24609405083573348938, 0.74202229271111558523),
32                                     je.valuesC(Complex.valueOf(5.2, -2.5)).sc(),
33                                     1.0e-15);
34      }
35  
36      @Test
37      public void testIssue150Plus() {
38          final double tol = 1.0e-15;
39          final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(-1, 1));
40          UnitTestUtils.assertEquals(Complex.valueOf(-0.05283804848930030197,  0.54805291345769017271),
41                                     je.valuesC(Complex.valueOf(2.5, 1)).sc(),
42                                     tol);
43          UnitTestUtils.assertEquals(Complex.valueOf(-0.60770261083279560398, -0.14952869024894608466),
44                                     je.valuesC(Complex.valueOf(2.5, 1)).dc(),
45                                     tol);
46          UnitTestUtils.assertEquals(Complex.valueOf(-0.83882158549142135917,  0.03452229522564651472),
47                                     je.valuesC(Complex.valueOf(2.5, 1)).nc(),
48                                     tol);
49          UnitTestUtils.assertEquals(Complex.valueOf(-0.17429449621856489159, -1.80783751829078560914),
50                                     je.valuesS(Complex.valueOf(2.5, 1)).cs(),
51                                     tol);
52          UnitTestUtils.assertEquals(Complex.valueOf(-0.16440435588711757777,  1.12468960756395418591),
53                                     je.valuesS(Complex.valueOf(2.5, 1)).ds(),
54                                     tol);
55          UnitTestUtils.assertEquals(Complex.valueOf( 0.20861268618691977878,  1.51043608734889061868),
56                                     je.valuesS(Complex.valueOf(2.5, 1)).ns(),
57                                     tol);
58          UnitTestUtils.assertEquals(Complex.valueOf(-0.12725233583887664864, -0.87053277198136117922),
59                                     je.valuesD(Complex.valueOf(2.5, 1)).sd(),
60                                     tol);
61          UnitTestUtils.assertEquals(Complex.valueOf(-1.55160242432190970322,  0.38178061795390252544),
62                                     je.valuesD(Complex.valueOf(2.5, 1)).cd(),
63                                     tol);
64          UnitTestUtils.assertEquals(Complex.valueOf( 1.28833766241760303452, -0.37381070022725694453),
65                                     je.valuesD(Complex.valueOf(2.5, 1)).nd(),
66                                     tol);
67          UnitTestUtils.assertEquals(Complex.valueOf( 0.08972834000183662533, -0.64966769410777501600),
68                                     je.valuesN(Complex.valueOf(2.5, 1)).sn(),
69                                     tol);
70          UnitTestUtils.assertEquals(Complex.valueOf(-1.19013278764664544420, -0.04898075605528078495),
71                                     je.valuesN(Complex.valueOf(2.5, 1)).cn(),
72                                     tol);
73          UnitTestUtils.assertEquals(Complex.valueOf( 0.71592277399023027709,  0.20772473029448836951),
74                                     je.valuesN(Complex.valueOf(2.5, 1)).dn(),
75                                     tol);
76      }
77  
78      @Test
79      public void testIssue150Minus() {
80          final double tol = 4.0e-15;
81          final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(-1, 1));
82          UnitTestUtils.assertEquals(Complex.valueOf( 0.185179781846526661883, -0.7341316302932100299),
83                                     je.valuesC(Complex.valueOf(2.5, -1)).sc(),
84                                     tol);
85          UnitTestUtils.assertEquals(Complex.valueOf( 0.036804110724415414398, -0.5315661866967806324),
86                                     je.valuesC(Complex.valueOf(2.5, -1)).dc(),
87                                     tol);
88          UnitTestUtils.assertEquals(Complex.valueOf(-0.728148159153380263318,  0.1867014747416195502),
89                                     je.valuesC(Complex.valueOf(2.5, -1)).nc(),
90                                     tol);
91          UnitTestUtils.assertEquals(Complex.valueOf( 0.323040127526322749710,  1.2806688349356319835),
92                                     je.valuesS(Complex.valueOf(2.5, -1)).cs(),
93                                     tol);
94          UnitTestUtils.assertEquals(Complex.valueOf( 0.6926494536300507479991, -0.1245833311369300158),
95                                     je.valuesS(Complex.valueOf(2.5, -1)).ds(),
96                                     tol);
97          UnitTestUtils.assertEquals(Complex.valueOf(-0.474323834329079345837, -0.8722045864335993302),
98                                     je.valuesS(Complex.valueOf(2.5, -1)).ns(),
99                                     tol);
100         UnitTestUtils.assertEquals(Complex.valueOf( 1.398488691791959747251,  0.2515390416720468003),
101                                    je.valuesD(Complex.valueOf(2.5, -1)).sd(),
102                                    tol);
103         UnitTestUtils.assertEquals(Complex.valueOf( 0.129629753901629389295,  1.8722580876874522195),
104                                    je.valuesD(Complex.valueOf(2.5, -1)).cd(),
105                                    tol);
106         UnitTestUtils.assertEquals(Complex.valueOf(-0.443943012743148934256, -1.3390792137858189218),
107                                    je.valuesD(Complex.valueOf(2.5, -1)).nd(),
108                                    tol);
109         UnitTestUtils.assertEquals(Complex.valueOf(-0.48119337969263266180,  0.88483656597829146168),
110                                    je.valuesN(Complex.valueOf(2.5, -1)).sn(),
111                                    tol);
112         UnitTestUtils.assertEquals(Complex.valueOf(-1.28862738480059428568, -0.33041164783612229823),
113                                    je.valuesN(Complex.valueOf(2.5, -1)).cn(),
114                                    tol);
115         UnitTestUtils.assertEquals(Complex.valueOf(-0.22306244463316206117,  0.67283023813989968132),
116                                    je.valuesN(Complex.valueOf(2.5, -1)).dn(),
117                                    tol);
118     }
119 
120     @Test
121     public void testWolframArcsn() {
122         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
123         // the reference value wolframZ comes from https://www.wolframalpha.com/input?i=InverseJacobiSN%282.5-0.1+i+%2C0.3%2B0.1i%29
124         // note that as shown in table https://dlmf.nist.gov/22.4.T3, sn(z + 2K) = -sn(z)
125         // and since sn is odd in z (because θ₁ is odd and θ₂, θ₃, θ₄ are all even), then sn(-z) = -sn(z)
126         // this implies that sn(2K - z) = sn(z)
127         // so despite we don't provide the same result as Wolfram, we provide a correct result
128         Complex wolframZ = new Complex(0.94236298773531348838, 1.92822841948038407820);
129         Complex k = LegendreEllipticIntegral.bigK(je.getM());
130         UnitTestUtils.assertEquals(k.multiply(2).subtract(wolframZ), je.arcsn(new Complex(2.5, -0.1)), 1.0e-15);
131     }
132 
133     @Test
134     public void testWolframArccn() {
135         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
136         // the reference value wolframZ comes from https://www.wolframalpha.com/input?i=InverseJacobiCN%282.5-0.1+i+%2C0.3%2B0.1i%29
137         final Complex wolframZ = new Complex(0.07230884246063775670, 1.35935692611563542744);
138         UnitTestUtils.assertEquals(wolframZ, je.arccn(new Complex(2.5, -0.1)), 1.0e-15);
139     }
140 
141     @Test
142     public void testWolframArcdn() {
143         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
144         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiDN%282.5-0.1+i+%2C0.3%2B0.1i%29
145         final Complex wolframZ = new Complex(0.15903444834380499952, 1.6312723209949430373);
146         UnitTestUtils.assertEquals(wolframZ, je.arcdn(new Complex(2.5, -0.1)), 1.0e-15);
147     }
148 
149     @Test
150     public void testWolframArccs() {
151         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
152         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiCS%282.5-0.1+i+%2C0.3%2B0.1i%29
153         // note that as shown in table https://dlmf.nist.gov/22.4.T2, one of the two cs periods is 2K
154         // so despite we don't provide the same result as Wolfram, we provide a correct result
155         final Complex wolframZ = new Complex(-3.0359823836145783448, -0.1010810531387431972);
156         final Complex k        = LegendreEllipticIntegral.bigK(je.getM());
157         final Complex period   = k.multiply(2);
158         UnitTestUtils.assertEquals(wolframZ.add(period), je.arccs(new Complex(2.5, -0.1)), 1.0e-15);
159     }
160 
161     @Test
162     public void testWolframArcds() {
163         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
164         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiDS%282.5-0.1+i+%2C0.3%2B0.1i%29
165         // note that as shown in table https://dlmf.nist.gov/22.4.T2, one of the two cs periods is 2K+2iK'
166         // so despite we don't provide the same result as Wolfram, we provide a correct result
167         final Complex wolframZ = new Complex(-3.29799820949072209724, -4.202477914142034207);
168         final Complex k      = LegendreEllipticIntegral.bigK(je.getM());
169         final Complex kPrime = LegendreEllipticIntegral.bigKPrime(je.getM());
170         final Complex period = k.add(kPrime.multiplyPlusI()).multiply(2);
171         UnitTestUtils.assertEquals(wolframZ.add(period), je.arcds(new Complex(2.5, -0.1)), 1.0e-15);
172     }
173 
174     @Test
175     public void testWolframArcns() {
176         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
177         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiNS%282.5-0.1+i+%2C0.3%2B0.1i%29
178         // note that as shown in table https://dlmf.nist.gov/22.4.T2, one of the two ns periods is 2iK'
179         // so despite we don't provide the same result as Wolfram, we provide a correct result
180         final Complex wolframZ = new Complex(0.130428467771173061681, -4.08174077348072795334);
181         final Complex kPrime   = LegendreEllipticIntegral.bigKPrime(je.getM());
182         final Complex period   = kPrime.multiply(new Complex(0, 2));
183         UnitTestUtils.assertEquals(wolframZ.add(period), je.arcns(new Complex(2.5, -0.1)), 1.0e-15);
184     }
185 
186     @Test
187     public void testWolframArcdc() {
188         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
189         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiDC%282.5-0.1+i+%2C0.3%2B0.1i%29
190         // note that as shown in table https://dlmf.nist.gov/22.4.T2, one of the two dc periods is 2iK'
191         // so despite we don't provide the same result as Wolfram, we provide a correct result
192         final Complex wolframZ = new Complex(1.578878353498834641592, 4.13977600222252116268406);
193         final Complex kPrime   = LegendreEllipticIntegral.bigKPrime(je.getM());
194         final Complex period   = kPrime.multiply(new Complex(0, 2));
195         UnitTestUtils.assertEquals(wolframZ.subtract(period), je.arcdc(new Complex(2.5, -0.1)), 1.0e-15);
196     }
197 
198     @Test
199     public void testWolframArcnc() {
200         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
201         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiNC%282.5-0.1+i+%2C0.3%2B0.1i%29
202         final Complex wolframZ = new Complex(1.228171217697117722621, 0.006214187083238678388730749);
203         UnitTestUtils.assertEquals(wolframZ, je.arcnc(new Complex(2.5, -0.1)), 1.0e-15);
204     }
205 
206     @Test
207     public void testWolframArcsc() {
208         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
209         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiSC%282.5-0.1+i+%2C0.3%2B0.1i%29
210         final Complex wolframZ = new Complex(1.26341293208997584885855, 0.012370090803027899483388605);
211         UnitTestUtils.assertEquals(wolframZ, je.arcsc(new Complex(2.5, -0.1)), 1.0e-15);
212     }
213 
214     @Test
215     public void testWolframArcnd() {
216         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
217         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiND%282.5-0.1+i+%2C0.3%2B0.1i%29
218         final Complex wolframZ = new Complex(1.504742584755344845407901, -1.4869490086301163397113928);
219         UnitTestUtils.assertEquals(wolframZ, je.arcnd(new Complex(2.5, -0.1)), 1.0e-15);
220     }
221 
222     @Test
223     public void testWolframArcsd() {
224         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
225         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiSD%282.5-0.1+i+%2C0.3%2B0.1i%29
226         final Complex wolframZ = new Complex(1.5881213420484595584158128, -1.1747797577661992518362122);
227         UnitTestUtils.assertEquals(wolframZ, je.arcsd(new Complex(2.5, -0.1)), 1.0e-15);
228     }
229 
230     @Test
231     public void testWolframArccd() {
232         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.1));
233         // the reference value comes from https://www.wolframalpha.com/input?i=InverseJacobiCD%282.5-0.1+i+%2C0.3%2B0.1i%29
234         final Complex wolframZ = new Complex(0.7669438335346942148909019, -1.87019319073859086886105089);
235         UnitTestUtils.assertEquals(wolframZ, je.arccd(new Complex(2.5, -0.1)), 1.0e-15);
236     }
237 
238     @Test
239     public void testBranchCutArccn() {
240         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.3, 0.0));
241         UnitTestUtils.assertEquals(new Complex(0.0, -1.3652045107), je.arccn(new Complex(2.5, +0.0)), 1.0e-10);
242         UnitTestUtils.assertEquals(new Complex(0.0, +1.3652045107), je.arccn(new Complex(2.5, -0.0)), 1.0e-10);
243     }
244 
245     @Test
246     public void testBranchCutArcdn() {
247         final FieldJacobiElliptic<Complex> je = JacobiEllipticBuilder.build(Complex.valueOf(0.7, 0.0));
248         UnitTestUtils.assertEquals(new Complex(0.0, -1.1513008795), je.arcdn(new Complex(1.9, +0.0)), 1.0e-10);
249         UnitTestUtils.assertEquals(new Complex(0.0, +1.1513008795), je.arcdn(new Complex(1.9, -0.0)), 1.0e-10);
250 
251         UnitTestUtils.assertEquals(new Complex(2.0753631353, -1.1247480245), je.arcdn(new Complex(0.3, +1.0e-11)), 1.0e-10);
252         UnitTestUtils.assertEquals(new Complex(2.0753631353, +1.1247480245), je.arcdn(new Complex(0.3, -1.0e-11)), 1.0e-10);
253         UnitTestUtils.assertEquals(new Complex(2.0753631353, -1.1247480245), je.arcdn(new Complex(0.3, +0.0)), 1.0e-10);
254 
255         // the following commented out test fails! We get the wrong Riemann sheet for negative zero on imaginary part
256 //        UnitTestUtils.assertEquals(new Complex(2.0753631353, +1.1247480245), je.arcdn(new Complex(0.3, -0.0)), 1.0e-10);
257 
258         UnitTestUtils.assertEquals(new Complex(4.150726270582776, -1.2596062674998643), je.arcdn(new Complex(-2.3, +1.0e-11)), 1.0e-10);
259         UnitTestUtils.assertEquals(new Complex(4.150726270582776, +1.2596062674998643), je.arcdn(new Complex(-2.3, -1.0e-11)), 1.0e-10);
260         UnitTestUtils.assertEquals(new Complex(4.150726270582776, -1.2596062674998643), je.arcdn(new Complex(-2.3, +0.0)), 1.0e-10);
261         UnitTestUtils.assertEquals(new Complex(4.150726270582776, +1.2596062674998643), je.arcdn(new Complex(-2.3, -0.0)), 1.0e-10);
262     }
263 
264 }