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 }