JacobiElliptic.java

  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. import org.hipparchus.special.elliptic.carlson.CarlsonEllipticIntegral;
  19. import org.hipparchus.special.elliptic.legendre.LegendreEllipticIntegral;
  20. import org.hipparchus.util.FastMath;

  21. /** Algorithm computing Jacobi elliptic functions.
  22.  * @since 2.0
  23.  */
  24. public abstract class JacobiElliptic {

  25.     /** Parameter of the function. */
  26.     private final double m;

  27.     /** Simple constructor.
  28.      * @param m parameter of the function
  29.      */
  30.     protected JacobiElliptic(final double m) {
  31.         this.m = m;
  32.     }

  33.     /** Get the parameter of the function.
  34.      * @return parameter of the function
  35.      */
  36.     public double getM() {
  37.         return m;
  38.     }

  39.     /** Evaluate the three principal Jacobi elliptic functions with pole at point n in Glaisher’s Notation.
  40.      * @param u argument of the functions
  41.      * @return copolar trio containing the three principal Jacobi
  42.      * elliptic functions {@code sn(u|m)}, {@code cn(u|m)}, and {@code dn(u|m)}.
  43.      */
  44.     public abstract CopolarN valuesN(double u);

  45.     /** Evaluate the three subsidiary Jacobi elliptic functions with pole at point s in Glaisher’s Notation.
  46.      * @param u argument of the functions
  47.      * @return copolar trio containing the three subsidiary Jacobi
  48.      * elliptic functions {@code cs(u|m)}, {@code ds(u|m)} and {@code ns(u|m)}.
  49.      */
  50.     public CopolarS valuesS(final double u) {
  51.         return new CopolarS(valuesN(u));
  52.     }

  53.     /** Evaluate the three subsidiary Jacobi elliptic functions with pole at point c in Glaisher’s Notation.
  54.      * @param u argument of the functions
  55.      * @return copolar trio containing the three subsidiary Jacobi
  56.      * elliptic functions {@code dc(u|m)}, {@code nc(u|m)}, and {@code sc(u|m)}.
  57.      */
  58.     public CopolarC valuesC(final double u) {
  59.         return new CopolarC(valuesN(u));
  60.     }

  61.     /** Evaluate the three subsidiary Jacobi elliptic functions with pole at point d in Glaisher’s Notation.
  62.      * @param u argument of the functions
  63.      * @return copolar trio containing the three subsidiary Jacobi
  64.      * elliptic functions {@code nd(u|m)}, {@code sd(u|m)}, and {@code cd(u|m)}.
  65.      */
  66.     public CopolarD valuesD(final double u) {
  67.         return new CopolarD(valuesN(u));
  68.     }

  69.     /** Evaluate inverse of Jacobi elliptic function sn.
  70.      * @param x value of Jacobi elliptic function {@code sn(u|m)}
  71.      * @return u such that {@code x=sn(u|m)}
  72.      * @since 2.1
  73.      */
  74.     public double arcsn(final double x) {
  75.         // p = n, q = c, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
  76.         return arcsp(x, -1, -getM());
  77.     }

  78.     /** Evaluate inverse of Jacobi elliptic function cn.
  79.      * @param x value of Jacobi elliptic function {@code cn(u|m)}
  80.      * @return u such that {@code x=cn(u|m)}
  81.      * @since 2.1
  82.      */
  83.     public double arccn(final double x) {
  84.         // p = c, q = n, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
  85.         return arcpq(x, 1, -getM());
  86.     }

  87.     /** Evaluate inverse of Jacobi elliptic function dn.
  88.      * @param x value of Jacobi elliptic function {@code dn(u|m)}
  89.      * @return u such that {@code x=dn(u|m)}
  90.      * @since 2.1
  91.      */
  92.     public double arcdn(final double x) {
  93.         // p = d, q = n, r = c, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
  94.         return arcpq(x, getM(), -1);
  95.     }

  96.     /** Evaluate inverse of Jacobi elliptic function cs.
  97.      * @param x value of Jacobi elliptic function {@code cs(u|m)}
  98.      * @return u such that {@code x=cs(u|m)}
  99.      * @since 2.1
  100.      */
  101.     public double arccs(final double x) {
  102.         // p = c, q = n, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
  103.         return arcps(x, 1, 1 - getM());
  104.     }

  105.     /** Evaluate inverse of Jacobi elliptic function ds.
  106.      * @param x value of Jacobi elliptic function {@code ds(u|m)}
  107.      * @return u such that {@code x=ds(u|m)}
  108.      * @since 2.1
  109.      */
  110.     public double arcds(final double x) {
  111.         // p = d, q = c, r = n, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
  112.         return arcps(x, getM() - 1, getM());
  113.     }

  114.     /** Evaluate inverse of Jacobi elliptic function ns.
  115.      * @param x value of Jacobi elliptic function {@code ns(u|m)}
  116.      * @return u such that {@code x=ns(u|m)}
  117.      * @since 2.1
  118.      */
  119.     public double arcns(final double x) {
  120.         // p = n, q = c, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
  121.         return arcps(x, -1, -getM());
  122.     }

  123.     /** Evaluate inverse of Jacobi elliptic function dc.
  124.      * @param x value of Jacobi elliptic function {@code dc(u|m)}
  125.      * @return u such that {@code x=dc(u|m)}
  126.      * @since 2.1
  127.      */
  128.     public double arcdc(final double x) {
  129.         // p = d, q = c, r = n, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
  130.         return arcpq(x, getM() - 1, 1);
  131.     }

  132.     /** Evaluate inverse of Jacobi elliptic function nc.
  133.      * @param x value of Jacobi elliptic function {@code nc(u|m)}
  134.      * @return u such that {@code x=nc(u|m)}
  135.      * @since 2.1
  136.      */
  137.     public double arcnc(final double x) {
  138.         // p = n, q = c, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
  139.         return arcpq(x, -1, 1 - getM());
  140.     }

  141.     /** Evaluate inverse of Jacobi elliptic function sc.
  142.      * @param x value of Jacobi elliptic function {@code sc(u|m)}
  143.      * @return u such that {@code x=sc(u|m)}
  144.      * @since 2.1
  145.      */
  146.     public double arcsc(final double x) {
  147.         // p = c, q = n, r = d, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
  148.         return arcsp(x, 1, 1 - getM());
  149.     }

  150.     /** Evaluate inverse of Jacobi elliptic function nd.
  151.      * @param x value of Jacobi elliptic function {@code nd(u|m)}
  152.      * @return u such that {@code x=nd(u|m)}
  153.      * @since 2.1
  154.      */
  155.     public double arcnd(final double x) {
  156.         // p = n, q = d, r = c, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
  157.         return arcpq(x, -getM(), getM() - 1);
  158.     }

  159.     /** Evaluate inverse of Jacobi elliptic function sd.
  160.      * @param x value of Jacobi elliptic function {@code sd(u|m)}
  161.      * @return u such that {@code x=sd(u|m)}
  162.      * @since 2.1
  163.      */
  164.     public double arcsd(final double x) {
  165.         // p = d, q = n, r = c, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, p)
  166.         return arcsp(x, getM(), getM() - 1);
  167.     }

  168.     /** Evaluate inverse of Jacobi elliptic function cd.
  169.      * @param x value of Jacobi elliptic function {@code cd(u|m)}
  170.      * @return u such that {@code x=cd(u|m)}
  171.      * @since 2.1
  172.      */
  173.     public double arccd(final double x) {
  174.         // p = c, q = d, r = n, see DLMF 19.25.29 for evaluating Δ⁡(q, p) and Δ⁡(r, q)
  175.         return arcpq(x, 1 - getM(), getM());
  176.     }

  177.     /** Evaluate inverse of Jacobi elliptic function ps.
  178.      * <p>
  179.      * Here p, q, r are any permutation of the letters c, d, n.
  180.      * </p>
  181.      * @param x value of Jacobi elliptic function {@code ps(u|m)}
  182.      * @param deltaQP Δ⁡(q, p) = q⁣s²⁡(u|m) - p⁣s²(u|m) (equation 19.5.28 of DLMF)
  183.      * @param deltaRP Δ⁡(r, p) = r⁣s²⁡(u|m) - p⁣s²⁡(u|m) (equation 19.5.28 of DLMF)
  184.      * @return u such that {@code x=ps(u|m)}
  185.      * @since 2.1
  186.      */
  187.     private double arcps(final double x, final double deltaQP, final double deltaRP) {
  188.         // see equation 19.25.32 in Digital Library of Mathematical Functions
  189.         // https://dlmf.nist.gov/19.25.E32
  190.         final double x2 = x * x;
  191.         return FastMath.copySign(CarlsonEllipticIntegral.rF(x2, x2 + deltaQP, x2 + deltaRP), x);
  192.     }

  193.     /** Evaluate inverse of Jacobi elliptic function sp.
  194.      * <p>
  195.      * Here p, q, r are any permutation of the letters c, d, n.
  196.      * </p>
  197.      * @param x value of Jacobi elliptic function {@code sp(u|m)}
  198.      * @param deltaQP Δ⁡(q, p) = q⁣s²⁡(u|m) - p⁣s²(u|m) (equation 19.5.28 of DLMF)
  199.      * @param deltaRP Δ⁡(r, p) = r⁣s²⁡(u|m) - p⁣s²⁡(u|m) (equation 19.5.28 of DLMF)
  200.      * @return u such that {@code x=sp(u|m)}
  201.      * @since 2.1
  202.      */
  203.     private double arcsp(final double x, final double deltaQP, final double deltaRP) {
  204.         // see equation 19.25.33 in Digital Library of Mathematical Functions
  205.         // https://dlmf.nist.gov/19.25.E33
  206.         final double x2 = x * x;
  207.         return x * CarlsonEllipticIntegral.rF(1, 1 + deltaQP * x2, 1 + deltaRP * x2);
  208.     }

  209.     /** Evaluate inverse of Jacobi elliptic function pq.
  210.      * <p>
  211.      * Here p, q, r are any permutation of the letters c, d, n.
  212.      * </p>
  213.      * @param x value of Jacobi elliptic function {@code pq(u|m)}
  214.      * @param deltaQP Δ⁡(q, p) = q⁣s²⁡(u|m) - p⁣s²(u|m) (equation 19.5.28 of DLMF)
  215.      * @param deltaRQ Δ⁡(r, q) = r⁣s²⁡(u|m) - q⁣s²⁡(u|m) (equation 19.5.28 of DLMF)
  216.      * @return u such that {@code x=pq(u|m)}
  217.      * @since 2.1
  218.      */
  219.     private double arcpq(final double x, final double deltaQP, final double deltaRQ) {
  220.         // see equation 19.25.34 in Digital Library of Mathematical Functions
  221.         // https://dlmf.nist.gov/19.25.E34
  222.         final double x2       = x * x;
  223.         final double w        = (1 - x2) / deltaQP;
  224.         final double positive = FastMath.sqrt(w) * CarlsonEllipticIntegral.rF(x2, 1, 1 + deltaRQ * w);
  225.         return x < 0 ? 2 * LegendreEllipticIntegral.bigK(getM()) - positive : positive;
  226.     }

  227. }