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.special.elliptic.carlson.CarlsonEllipticIntegral;
20  import org.hipparchus.special.elliptic.legendre.LegendreEllipticIntegral;
21  import org.hipparchus.util.FastMath;
22  
23  /** Algorithm computing Jacobi elliptic functions.
24   * @since 2.0
25   */
26  public abstract class JacobiElliptic {
27  
28      /** Parameter of the function. */
29      private final double m;
30  
31      /** Simple constructor.
32       * @param m parameter of the function
33       */
34      protected JacobiElliptic(final double m) {
35          this.m = m;
36      }
37  
38      /** Get the parameter of the function.
39       * @return parameter of the function
40       */
41      public double getM() {
42          return m;
43      }
44  
45      /** Evaluate the three principal Jacobi elliptic functions with pole at point n in Glaisher’s Notation.
46       * @param u argument of the functions
47       * @return copolar trio containing the three principal Jacobi
48       * elliptic functions {@code sn(u|m)}, {@code cn(u|m)}, and {@code dn(u|m)}.
49       */
50      public abstract CopolarN valuesN(double u);
51  
52      /** Evaluate the three subsidiary Jacobi elliptic functions with pole at point s in Glaisher’s Notation.
53       * @param u argument of the functions
54       * @return copolar trio containing the three subsidiary Jacobi
55       * elliptic functions {@code cs(u|m)}, {@code ds(u|m)} and {@code ns(u|m)}.
56       */
57      public CopolarS valuesS(final double u) {
58          return new CopolarS(valuesN(u));
59      }
60  
61      /** Evaluate the three subsidiary Jacobi elliptic functions with pole at point c in Glaisher’s Notation.
62       * @param u argument of the functions
63       * @return copolar trio containing the three subsidiary Jacobi
64       * elliptic functions {@code dc(u|m)}, {@code nc(u|m)}, and {@code sc(u|m)}.
65       */
66      public CopolarC valuesC(final double u) {
67          return new CopolarC(valuesN(u));
68      }
69  
70      /** Evaluate the three subsidiary Jacobi elliptic functions with pole at point d in Glaisher’s Notation.
71       * @param u argument of the functions
72       * @return copolar trio containing the three subsidiary Jacobi
73       * elliptic functions {@code nd(u|m)}, {@code sd(u|m)}, and {@code cd(u|m)}.
74       */
75      public CopolarD valuesD(final double u) {
76          return new CopolarD(valuesN(u));
77      }
78  
79      /** Evaluate inverse of Jacobi elliptic function sn.
80       * @param x value of Jacobi elliptic function {@code sn(u|m)}
81       * @return u such that {@code x=sn(u|m)}
82       * @since 2.1
83       */
84      public double arcsn(final double x) {
85          // p = n, q = c, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
86          return arcsp(x, -1, -getM());
87      }
88  
89      /** Evaluate inverse of Jacobi elliptic function cn.
90       * @param x value of Jacobi elliptic function {@code cn(u|m)}
91       * @return u such that {@code x=cn(u|m)}
92       * @since 2.1
93       */
94      public double arccn(final double x) {
95          // p = c, q = n, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
96          return arcpq(x, 1, -getM());
97      }
98  
99      /** Evaluate inverse of Jacobi elliptic function dn.
100      * @param x value of Jacobi elliptic function {@code dn(u|m)}
101      * @return u such that {@code x=dn(u|m)}
102      * @since 2.1
103      */
104     public double arcdn(final double x) {
105         // p = d, q = n, r = c, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
106         return arcpq(x, getM(), -1);
107     }
108 
109     /** Evaluate inverse of Jacobi elliptic function cs.
110      * @param x value of Jacobi elliptic function {@code cs(u|m)}
111      * @return u such that {@code x=cs(u|m)}
112      * @since 2.1
113      */
114     public double arccs(final double x) {
115         // p = c, q = n, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
116         return arcps(x, 1, 1 - getM());
117     }
118 
119     /** Evaluate inverse of Jacobi elliptic function ds.
120      * @param x value of Jacobi elliptic function {@code ds(u|m)}
121      * @return u such that {@code x=ds(u|m)}
122      * @since 2.1
123      */
124     public double arcds(final double x) {
125         // p = d, q = c, r = n, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
126         return arcps(x, getM() - 1, getM());
127     }
128 
129     /** Evaluate inverse of Jacobi elliptic function ns.
130      * @param x value of Jacobi elliptic function {@code ns(u|m)}
131      * @return u such that {@code x=ns(u|m)}
132      * @since 2.1
133      */
134     public double arcns(final double x) {
135         // p = n, q = c, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
136         return arcps(x, -1, -getM());
137     }
138 
139     /** Evaluate inverse of Jacobi elliptic function dc.
140      * @param x value of Jacobi elliptic function {@code dc(u|m)}
141      * @return u such that {@code x=dc(u|m)}
142      * @since 2.1
143      */
144     public double arcdc(final double x) {
145         // p = d, q = c, r = n, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
146         return arcpq(x, getM() - 1, 1);
147     }
148 
149     /** Evaluate inverse of Jacobi elliptic function nc.
150      * @param x value of Jacobi elliptic function {@code nc(u|m)}
151      * @return u such that {@code x=nc(u|m)}
152      * @since 2.1
153      */
154     public double arcnc(final double x) {
155         // p = n, q = c, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
156         return arcpq(x, -1, 1 - getM());
157     }
158 
159     /** Evaluate inverse of Jacobi elliptic function sc.
160      * @param x value of Jacobi elliptic function {@code sc(u|m)}
161      * @return u such that {@code x=sc(u|m)}
162      * @since 2.1
163      */
164     public double arcsc(final double x) {
165         // p = c, q = n, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
166         return arcsp(x, 1, 1 - getM());
167     }
168 
169     /** Evaluate inverse of Jacobi elliptic function nd.
170      * @param x value of Jacobi elliptic function {@code nd(u|m)}
171      * @return u such that {@code x=nd(u|m)}
172      * @since 2.1
173      */
174     public double arcnd(final double x) {
175         // p = n, q = d, r = c, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
176         return arcpq(x, -getM(), getM() - 1);
177     }
178 
179     /** Evaluate inverse of Jacobi elliptic function sd.
180      * @param x value of Jacobi elliptic function {@code sd(u|m)}
181      * @return u such that {@code x=sd(u|m)}
182      * @since 2.1
183      */
184     public double arcsd(final double x) {
185         // p = d, q = n, r = c, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
186         return arcsp(x, getM(), getM() - 1);
187     }
188 
189     /** Evaluate inverse of Jacobi elliptic function cd.
190      * @param x value of Jacobi elliptic function {@code cd(u|m)}
191      * @return u such that {@code x=cd(u|m)}
192      * @since 2.1
193      */
194     public double arccd(final double x) {
195         // p = c, q = d, r = n, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
196         return arcpq(x, 1 - getM(), getM());
197     }
198 
199     /** Evaluate inverse of Jacobi elliptic function ps.
200      * <p>
201      * Here p, q, r are any permutation of the letters c, d, n.
202      * </p>
203      * @param x value of Jacobi elliptic function {@code ps(u|m)}
204      * @param deltaQP Δ⁡(q, p) = q⁣s²⁡(u|m) - p⁣s²(u|m) (equation 19.5.28 of DLMF)
205      * @param deltaRP Δ⁡(r, p) = r⁣s²⁡(u|m) - p⁣s²⁡(u|m) (equation 19.5.28 of DLMF)
206      * @return u such that {@code x=ps(u|m)}
207      * @since 2.1
208      */
209     private double arcps(final double x, final double deltaQP, final double deltaRP) {
210         // see equation 19.25.32 in Digital Library of Mathematical Functions
211         // https://dlmf.nist.gov/19.25.E32
212         final double x2 = x * x;
213         return FastMath.copySign(CarlsonEllipticIntegral.rF(x2, x2 + deltaQP, x2 + deltaRP), x);
214     }
215 
216     /** Evaluate inverse of Jacobi elliptic function sp.
217      * <p>
218      * Here p, q, r are any permutation of the letters c, d, n.
219      * </p>
220      * @param x value of Jacobi elliptic function {@code sp(u|m)}
221      * @param deltaQP Δ⁡(q, p) = q⁣s²⁡(u|m) - p⁣s²(u|m) (equation 19.5.28 of DLMF)
222      * @param deltaRP Δ⁡(r, p) = r⁣s²⁡(u|m) - p⁣s²⁡(u|m) (equation 19.5.28 of DLMF)
223      * @return u such that {@code x=sp(u|m)}
224      * @since 2.1
225      */
226     private double arcsp(final double x, final double deltaQP, final double deltaRP) {
227         // see equation 19.25.33 in Digital Library of Mathematical Functions
228         // https://dlmf.nist.gov/19.25.E33
229         final double x2 = x * x;
230         return x * CarlsonEllipticIntegral.rF(1, 1 + deltaQP * x2, 1 + deltaRP * x2);
231     }
232 
233     /** Evaluate inverse of Jacobi elliptic function pq.
234      * <p>
235      * Here p, q, r are any permutation of the letters c, d, n.
236      * </p>
237      * @param x value of Jacobi elliptic function {@code pq(u|m)}
238      * @param deltaQP Δ⁡(q, p) = q⁣s²⁡(u|m) - p⁣s²(u|m) (equation 19.5.28 of DLMF)
239      * @param deltaRQ Δ⁡(r, q) = r⁣s²⁡(u|m) - q⁣s²⁡(u|m) (equation 19.5.28 of DLMF)
240      * @return u such that {@code x=pq(u|m)}
241      * @since 2.1
242      */
243     private double arcpq(final double x, final double deltaQP, final double deltaRQ) {
244         // see equation 19.25.34 in Digital Library of Mathematical Functions
245         // https://dlmf.nist.gov/19.25.E34
246         final double x2       = x * x;
247         final double w        = (1 - x2) / deltaQP;
248         final double positive = FastMath.sqrt(w) * CarlsonEllipticIntegral.rF(x2, 1, 1 + deltaRQ * w);
249         return x < 0 ? 2 * LegendreEllipticIntegral.bigK(getM()) - positive : positive;
250     }
251 
252 }