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) = qs²(u|m) - ps²(u|m) (equation 19.5.28 of DLMF)
205 * @param deltaRP Δ(r, p) = rs²(u|m) - ps²(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) = qs²(u|m) - ps²(u|m) (equation 19.5.28 of DLMF)
222 * @param deltaRP Δ(r, p) = rs²(u|m) - ps²(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) = qs²(u|m) - ps²(u|m) (equation 19.5.28 of DLMF)
239 * @param deltaRQ Δ(r, q) = rs²(u|m) - qs²(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 }