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 org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.special.elliptic.legendre.LegendreEllipticIntegral;
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  class FieldJacobiThetaTest {
31  
32      @Test
33      void testNoConvergence() {
34          doTestNoConvergence(Binary64Field.getInstance());
35      }
36  
37      private <T extends CalculusFieldElement<T>> void doTestNoConvergence(Field<T> field) {
38          assertTrue(new FieldJacobiTheta<>(field.getZero().newInstance(Double.NaN)).values(field.getZero()).theta1().isNaN());
39      }
40  
41      @Test
42      void testRealZero() {
43          doTestRealZero(Binary64Field.getInstance());
44      }
45  
46      private <T extends CalculusFieldElement<T>> void doTestRealZero(Field<T> field) {
47          final T k      = field.getZero().newInstance(0.675);
48          final T m      = k.multiply(k);
49          final T q      = LegendreEllipticIntegral.nome(m);
50          final T t3Ref  = field.getOne().add(q.
51                                              add(FastMath.pow(q, 4)).
52                                              add(FastMath.pow(q, 9)).
53                                              add(FastMath.pow(q, 16)).multiply(2));
54          final T theta3 = new FieldJacobiTheta<>(q).values(field.getZero()).theta3();
55          assertEquals(t3Ref.getReal(), theta3.getReal(), 1.0e-12);
56      }
57  
58      @Test
59      void testQuarterPeriod() {
60          doTestQuarterPeriod(Binary64Field.getInstance());
61      }
62  
63      private <T extends CalculusFieldElement<T>> void doTestQuarterPeriod(Field<T> field) {
64          final T k      = field.getZero().newInstance(0.675);
65          final T m      = k.multiply(k);
66          final T q      = LegendreEllipticIntegral.nome(m);
67          final T theta3 = new FieldJacobiTheta<>(q).values(field.getZero()).theta3();
68          assertEquals(LegendreEllipticIntegral.bigK(m).getReal(),
69                              theta3.multiply(theta3).multiply(MathUtils.SEMI_PI).getReal(),
70                              1.0e-12);
71      }
72  
73      @Test
74      void testEllipticFunctions() {
75          doTestEllipticFunctions(Binary64Field.getInstance());
76      }
77  
78      private <T extends CalculusFieldElement<T>> void doTestEllipticFunctions(Field<T> field) {
79  
80          final T                   z      = field.getZero().newInstance(1.3);
81          final T                   k      = field.getZero().newInstance(0.675);
82          final T                   m      = k.multiply(k);
83          final T                   q      =  LegendreEllipticIntegral.nome(m);
84          final T                   bigK   = LegendreEllipticIntegral.bigK(m);
85          final T                   zeta   = z.divide(bigK).multiply(MathUtils.SEMI_PI);
86          final FieldJacobiTheta<T> jt     = new FieldJacobiTheta<>(q);
87          final FieldTheta<T>       theta0 = jt.values(field.getZero());
88          final FieldTheta<T>       thetaZ = jt.values(zeta);
89  
90          // the theta functions are related to the elliptic functions
91          // see https://dlmf.nist.gov/22.2
92          final FieldJacobiElliptic<T> je = JacobiEllipticBuilder.build(k.multiply(k));
93          final FieldCopolarN<T> valuesN = je.valuesN(z);
94          final FieldCopolarD<T> valuesD = je.valuesD(z);
95          final FieldCopolarC<T> valuesC = je.valuesC(z);
96          final T t02 = theta0.theta2();
97          final T t03 = theta0.theta3();
98          final T t04 = theta0.theta4();
99          final T tz1 = thetaZ.theta1();
100         final T tz2 = thetaZ.theta2();
101         final T tz3 = thetaZ.theta3();
102         final T tz4 = thetaZ.theta4();
103         assertEquals(valuesN.sn().getReal(), t03.multiply(tz1)              .divide(t02.multiply(tz4)).getReal(),               3.0e-15);
104         assertEquals(valuesN.cn().getReal(), t04.multiply(tz2)              .divide(t02.multiply(tz4)).getReal(),               3.0e-15);
105         assertEquals(valuesN.dn().getReal(), t04.multiply(tz3)              .divide(t03.multiply(tz4)).getReal(),               3.0e-15);
106         assertEquals(valuesD.sd().getReal(), t03.multiply(t03).multiply(tz1).divide(t02.multiply(t04).multiply(tz3)).getReal(), 3.0e-15);
107         assertEquals(valuesD.cd().getReal(), t03.multiply(tz2)              .divide(t02.multiply(tz3)).getReal(),               3.0e-15);
108         assertEquals(valuesC.sc().getReal(), t03.multiply(tz1)              .divide(t04.multiply(tz2)).getReal(),               3.0e-15);
109 
110     }
111 
112 }