CarlsonEllipticIntegral.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.carlson;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.complex.Complex;
  20. import org.hipparchus.complex.FieldComplex;
  21. import org.hipparchus.util.FastMath;

  22. /** Elliptic integrals in Carlson symmetric form.
  23.  * <p>
  24.  * This utility class computes the various symmetric elliptic
  25.  * integrals defined as:
  26.  * \[
  27.  *   \left\{\begin{align}
  28.  *   R_F(x,y,z)   &amp;= \frac{1}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{s(t)}\\
  29.  *   R_J(x,y,z,p) &amp;= \frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{s(t)(t+p)}\\
  30.  *   R_G(x,y,z)   &amp;= \frac{1}{4}\int_{0}^{\infty}\frac{1}{s(t)}
  31.                      \left(\frac{x}{t+x}+\frac{y}{t+y}+\frac{z}{t+z}\right)t\mathrm{d}t\\
  32.  *   R_D(x,y,z)   &amp;= R_J(x,y,z,z)\\
  33.  *   R_C(x,y)     &amp;= R_F(x,y,y)
  34.  *   \end{align}\right.
  35.  * \]
  36.  * </p>
  37.  * <p>
  38.  * where
  39.  * \[
  40.  *   s(t) = \sqrt{t+x}\sqrt{t+y}\sqrt{t+z}
  41.  * \]
  42.  * </p>
  43.  * <p>
  44.  * The algorithms used are based on the duplication method as described in
  45.  * B. C. Carlson 1995 paper "Numerical computation of real or complex
  46.  * elliptic integrals", with the improvements described in the appendix
  47.  * of B. C. Carlson and James FitzSimons 2000 paper "Reduction theorems
  48.  * for elliptic integrands with the square root of two quadratic factors".
  49.  * They are also described in <a href="https://dlmf.nist.gov/19.36#i">section 19.36(i)</a>
  50.  * of Digital Library of Mathematical Functions.
  51.  * </p>
  52.  * <p>
  53.  * <em>
  54.  * Beware that when computing elliptic integrals in the complex plane,
  55.  * many issues arise due to branch cuts. See the
  56.  * <a href="https://www.hipparchus.org/hipparchus-core/special.html#Elliptic_functions_and_integrals">user guide</a>
  57.  * for a thorough explanation.
  58.  * </em>
  59.  * </p>
  60.  * @since 2.0
  61.  */
  62. public class CarlsonEllipticIntegral {

  63.     /** Private constructor for a utility class.
  64.      */
  65.     private CarlsonEllipticIntegral() {
  66.     }

  67.     /** Compute Carlson elliptic integral R<sub>C</sub>.
  68.      * <p>
  69.      * The Carlson elliptic integral R<sub>C</sub>is defined as
  70.      * \[
  71.      *   R_C(x,y,z)=R_F(x,y,y)=\frac{1}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}(t+y)}
  72.      * \]
  73.      * </p>
  74.      * @param x first symmetric variable of the integral
  75.      * @param y second symmetric variable of the integral
  76.      * @return Carlson elliptic integral R<sub>C</sub>
  77.      */
  78.     public static double rC(final double x, final double y) {
  79.         if (y < 0) {
  80.             // y is on the branch cut, we must use a transformation to get the Cauchy principal value
  81.             // see equation 2.14 in Carlson[1995]
  82.             final double xMy = x - y;
  83.             return FastMath.sqrt(x / xMy) * new RcRealDuplication(xMy, -y).integral();
  84.         } else {
  85.             return new RcRealDuplication(x, y).integral();
  86.         }
  87.     }

  88.     /** Compute Carlson elliptic integral R<sub>C</sub>.
  89.      * <p>
  90.      * The Carlson elliptic integral R<sub>C</sub>is defined as
  91.      * \[
  92.      *   R_C(x,y,z)=R_F(x,y,y)=\frac{1}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}(t+y)}
  93.      * \]
  94.      * </p>
  95.      * @param x first symmetric variable of the integral
  96.      * @param y second symmetric variable of the integral
  97.      * @param <T> type of the field elements
  98.      * @return Carlson elliptic integral R<sub>C</sub>
  99.      */
  100.     public static <T extends CalculusFieldElement<T>> T rC(final T x, final T y) {
  101.         if (y.getReal() < 0) {
  102.             // y is on the branch cut, we must use a transformation to get the Cauchy principal value
  103.             // see equation 2.14 in Carlson[1995]
  104.             final T xMy = x.subtract(y);
  105.             return FastMath.sqrt(x.divide(xMy)).multiply(new RcFieldDuplication<>(xMy, y.negate()).integral());
  106.         } else {
  107.             return new RcFieldDuplication<>(x, y).integral();
  108.         }
  109.     }

  110.     /** Compute Carlson elliptic integral R<sub>C</sub>.
  111.      * <p>
  112.      * The Carlson elliptic integral R<sub>C</sub>is defined as
  113.      * \[
  114.      *   R_C(x,y,z)=R_F(x,y,y)=\frac{1}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}(t+y)}
  115.      * \]
  116.      * </p>
  117.      * @param x first symmetric variable of the integral
  118.      * @param y second symmetric variable of the integral
  119.      * @return Carlson elliptic integral R<sub>C</sub>
  120.      */
  121.     public static Complex rC(final Complex x, final Complex y) {
  122.         if (y.getImaginaryPart() == 0 && y.getRealPart() < 0) {
  123.             // y is on the branch cut, we must use a transformation to get the Cauchy principal value
  124.             // see equation 2.14 in Carlson[1995]
  125.             final Complex xMy = x.subtract(y);
  126.             return FastMath.sqrt(x.divide(xMy)).multiply(new RcFieldDuplication<>(xMy, y.negate()).integral());
  127.         } else {
  128.             return new RcFieldDuplication<>(x, y).integral();
  129.         }
  130.     }

  131.     /** Compute Carlson elliptic integral R<sub>C</sub>.
  132.      * <p>
  133.      * The Carlson elliptic integral R<sub>C</sub>is defined as
  134.      * \[
  135.      *   R_C(x,y,z)=R_F(x,y,y)=\frac{1}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}(t+y)}
  136.      * \]
  137.      * </p>
  138.      * @param x first symmetric variable of the integral
  139.      * @param y second symmetric variable of the integral
  140.      * @param <T> type of the field elements
  141.      * @return Carlson elliptic integral R<sub>C</sub>
  142.      */
  143.     public static <T extends CalculusFieldElement<T>> FieldComplex<T> rC(final FieldComplex<T> x, final FieldComplex<T> y) {
  144.         if (y.getImaginaryPart().isZero() && y.getRealPart().getReal() < 0) {
  145.             // y is on the branch cut, we must use a transformation to get the Cauchy principal value
  146.             // see equation 2.14 in Carlson[1995]
  147.             final FieldComplex<T> xMy = x.subtract(y);
  148.             return FastMath.sqrt(x.divide(xMy)).multiply(new RcFieldDuplication<>(xMy, y.negate()).integral());
  149.         } else {
  150.             return new RcFieldDuplication<>(x, y).integral();
  151.         }
  152.     }

  153.     /** Compute Carlson elliptic integral R<sub>F</sub>.
  154.      * <p>
  155.      * The Carlson elliptic integral R<sub>F</sub> is defined as
  156.      * \[
  157.      *   R_F(x,y,z)=\frac{1}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}}
  158.      * \]
  159.      * </p>
  160.      * @param x first symmetric variable of the integral
  161.      * @param y second symmetric variable of the integral
  162.      * @param z third symmetric variable of the integral
  163.      * @return Carlson elliptic integral R<sub>F</sub>
  164.      */
  165.     public static double rF(final double x, final double y, final double z) {
  166.         return new RfRealDuplication(x, y, z).integral();
  167.     }

  168.     /** Compute Carlson elliptic integral R<sub>F</sub>.
  169.      * <p>
  170.      * The Carlson elliptic integral R<sub>F</sub> is defined as
  171.      * \[
  172.      *   R_F(x,y,z)=\frac{1}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}}
  173.      * \]
  174.      * </p>
  175.      * @param x first symmetric variable of the integral
  176.      * @param y second symmetric variable of the integral
  177.      * @param z third symmetric variable of the integral
  178.      * @param <T> type of the field elements
  179.      * @return Carlson elliptic integral R<sub>F</sub>
  180.      */
  181.     public static <T extends CalculusFieldElement<T>> T rF(final T x, final T y, final T z) {
  182.         return new RfFieldDuplication<>(x, y, z).integral();
  183.     }

  184.     /** Compute Carlson elliptic integral R<sub>F</sub>.
  185.      * <p>
  186.      * The Carlson elliptic integral R<sub>F</sub> is defined as
  187.      * \[
  188.      *   R_F(x,y,z)=\frac{1}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}}
  189.      * \]
  190.      * </p>
  191.      * @param x first symmetric variable of the integral
  192.      * @param y second symmetric variable of the integral
  193.      * @param z third symmetric variable of the integral
  194.      * @return Carlson elliptic integral R<sub>F</sub>
  195.      */
  196.     public static Complex rF(final Complex x, final Complex y, final Complex z) {
  197.         return new RfFieldDuplication<>(x, y, z).integral();
  198.     }

  199.     /** Compute Carlson elliptic integral R<sub>F</sub>.
  200.      * <p>
  201.      * The Carlson elliptic integral R<sub>F</sub> is defined as
  202.      * \[
  203.      *   R_F(x,y,z)=\frac{1}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}}
  204.      * \]
  205.      * </p>
  206.      * @param x first symmetric variable of the integral
  207.      * @param y second symmetric variable of the integral
  208.      * @param z third symmetric variable of the integral
  209.      * @param <T> type of the field elements
  210.      * @return Carlson elliptic integral R<sub>F</sub>
  211.      */
  212.     public static <T extends CalculusFieldElement<T>> FieldComplex<T> rF(final FieldComplex<T> x, final FieldComplex<T> y, final FieldComplex<T> z) {
  213.         return new RfFieldDuplication<>(x, y, z).integral();
  214.     }

  215.     /** Compute Carlson elliptic integral R<sub>J</sub>.
  216.      * <p>
  217.      * The Carlson elliptic integral R<sub>J</sub> is defined as
  218.      * \[
  219.      *   R_J(x,y,z,p)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+p)}
  220.      * \]
  221.      * </p>
  222.      * @param x first symmetric variable of the integral
  223.      * @param y second symmetric variable of the integral
  224.      * @param z third symmetric variable of the integral
  225.      * @param p fourth <em>not</em> symmetric variable of the integral
  226.      * @return Carlson elliptic integral R<sub>J</sub>
  227.      */
  228.     public static double rJ(final double x, final double y, final double z, final double p) {
  229.         final double delta = (p - x) * (p - y) * (p - z);
  230.         return rJ(x, y, z, p, delta);
  231.     }

  232.     /** Compute Carlson elliptic integral R<sub>J</sub>.
  233.      * <p>
  234.      * The Carlson elliptic integral R<sub>J</sub> is defined as
  235.      * \[
  236.      *   R_J(x,y,z,p)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+p)}
  237.      * \]
  238.      * </p>
  239.      * @param x first symmetric variable of the integral
  240.      * @param y second symmetric variable of the integral
  241.      * @param z third symmetric variable of the integral
  242.      * @param p fourth <em>not</em> symmetric variable of the integral
  243.      * @param delta precomputed value of (p-x)(p-y)(p-z)
  244.      * @return Carlson elliptic integral R<sub>J</sub>
  245.      */
  246.     public static double rJ(final double x, final double y, final double z, final double p, final double delta) {
  247.         return new RjRealDuplication(x, y, z, p, delta).integral();
  248.     }

  249.     /** Compute Carlson elliptic integral R<sub>J</sub>.
  250.      * <p>
  251.      * The Carlson elliptic integral R<sub>J</sub> is defined as
  252.      * \[
  253.      *   R_J(x,y,z,p)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+p)}
  254.      * \]
  255.      * </p>
  256.      * @param x first symmetric variable of the integral
  257.      * @param y second symmetric variable of the integral
  258.      * @param z third symmetric variable of the integral
  259.      * @param p fourth <em>not</em> symmetric variable of the integral
  260.      * @param <T> type of the field elements
  261.      * @return Carlson elliptic integral R<sub>J</sub>
  262.      */
  263.     public static <T extends CalculusFieldElement<T>> T rJ(final T x, final T y, final T z, final T p) {
  264.         final T delta = p.subtract(x).multiply(p.subtract(y)).multiply(p.subtract(z));
  265.         return new RjFieldDuplication<>(x, y, z, p, delta). integral();
  266.     }

  267.     /** Compute Carlson elliptic integral R<sub>J</sub>.
  268.      * <p>
  269.      * The Carlson elliptic integral R<sub>J</sub> is defined as
  270.      * \[
  271.      *   R_J(x,y,z,p)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+p)}
  272.      * \]
  273.      * </p>
  274.      * @param x first symmetric variable of the integral
  275.      * @param y second symmetric variable of the integral
  276.      * @param z third symmetric variable of the integral
  277.      * @param p fourth <em>not</em> symmetric variable of the integral
  278.      * @param delta precomputed value of (p-x)(p-y)(p-z)
  279.      * @param <T> type of the field elements
  280.      * @return Carlson elliptic integral R<sub>J</sub>
  281.      */
  282.     public static <T extends CalculusFieldElement<T>> T rJ(final T x, final T y, final T z, final T p, final T delta) {
  283.         return new RjFieldDuplication<>(x, y, z, p, delta).integral();
  284.     }

  285.     /** Compute Carlson elliptic integral R<sub>J</sub>.
  286.      * <p>
  287.      * The Carlson elliptic integral R<sub>J</sub> is defined as
  288.      * \[
  289.      *   R_J(x,y,z,p)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+p)}
  290.      * \]
  291.      * </p>
  292.      * @param x first symmetric variable of the integral
  293.      * @param y second symmetric variable of the integral
  294.      * @param z third symmetric variable of the integral
  295.      * @param p fourth <em>not</em> symmetric variable of the integral
  296.      * @return Carlson elliptic integral R<sub>J</sub>
  297.      */
  298.     public static Complex rJ(final Complex x, final Complex y, final Complex z, final Complex p) {
  299.         final Complex delta = p.subtract(x).multiply(p.subtract(y)).multiply(p.subtract(z));
  300.         return new RjFieldDuplication<>(x, y, z, p, delta).integral();
  301.     }

  302.     /** Compute Carlson elliptic integral R<sub>J</sub>.
  303.      * <p>
  304.      * The Carlson elliptic integral R<sub>J</sub> is defined as
  305.      * \[
  306.      *   R_J(x,y,z,p)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+p)}
  307.      * \]
  308.      * </p>
  309.      * @param x first symmetric variable of the integral
  310.      * @param y second symmetric variable of the integral
  311.      * @param z third symmetric variable of the integral
  312.      * @param p fourth <em>not</em> symmetric variable of the integral
  313.      * @param delta precomputed value of (p-x)(p-y)(p-z)
  314.      * @return Carlson elliptic integral R<sub>J</sub>
  315.      */
  316.     public static Complex rJ(final Complex x, final Complex y, final Complex z, final Complex p, final Complex delta) {
  317.         return new RjFieldDuplication<>(x, y, z, p, delta).integral();
  318.     }

  319.     /** Compute Carlson elliptic integral R<sub>J</sub>.
  320.      * <p>
  321.      * The Carlson elliptic integral R<sub>J</sub> is defined as
  322.      * \[
  323.      *   R_J(x,y,z,p)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+p)}
  324.      * \]
  325.      * </p>
  326.      * @param x first symmetric variable of the integral
  327.      * @param y second symmetric variable of the integral
  328.      * @param z third symmetric variable of the integral
  329.      * @param p fourth <em>not</em> symmetric variable of the integral
  330.      * @param <T> type of the field elements
  331.      * @return Carlson elliptic integral R<sub>J</sub>
  332.      */
  333.     public static <T extends CalculusFieldElement<T>> FieldComplex<T> rJ(final FieldComplex<T> x, final FieldComplex<T> y,
  334.                                                                          final FieldComplex<T> z, final FieldComplex<T> p) {
  335.         final FieldComplex<T> delta = p.subtract(x).multiply(p.subtract(y)).multiply(p.subtract(z));
  336.         return new RjFieldDuplication<>(x, y, z, p, delta).integral();
  337.     }

  338.     /** Compute Carlson elliptic integral R<sub>J</sub>.
  339.      * <p>
  340.      * The Carlson elliptic integral R<sub>J</sub> is defined as
  341.      * \[
  342.      *   R_J(x,y,z,p)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+p)}
  343.      * \]
  344.      * </p>
  345.      * @param x first symmetric variable of the integral
  346.      * @param y second symmetric variable of the integral
  347.      * @param z third symmetric variable of the integral
  348.      * @param p fourth <em>not</em> symmetric variable of the integral
  349.      * @param delta precomputed value of (p-x)(p-y)(p-z)
  350.      * @param <T> type of the field elements
  351.      * @return Carlson elliptic integral R<sub>J</sub>
  352.      */
  353.     public static <T extends CalculusFieldElement<T>> FieldComplex<T> rJ(final FieldComplex<T> x, final FieldComplex<T> y,
  354.                                                                          final FieldComplex<T> z, final FieldComplex<T> p,
  355.                                                                          final FieldComplex<T> delta) {
  356.         return new RjFieldDuplication<>(x, y, z, p, delta).integral();
  357.     }

  358.     /** Compute Carlson elliptic integral R<sub>D</sub>.
  359.      * <p>
  360.      * The Carlson elliptic integral R<sub>D</sub> is defined as
  361.      * \[
  362.      *   R_D(x,y,z)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+z)}
  363.      * \]
  364.      * </p>
  365.      * @param x first symmetric variable of the integral
  366.      * @param y second symmetric variable of the integral
  367.      * @param z third symmetric variable of the integral
  368.      * @return Carlson elliptic integral R<sub>D</sub>
  369.      */
  370.     public static double rD(final double x, final double y, final double z) {
  371.         return new RdRealDuplication(x, y, z).integral();
  372.     }

  373.     /** Compute Carlson elliptic integral R<sub>D</sub>.
  374.      * <p>
  375.      * The Carlson elliptic integral R<sub>D</sub> is defined as
  376.      * \[
  377.      *   R_D(x,y,z)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+z)}
  378.      * \]
  379.      * </p>
  380.      * @param x first symmetric variable of the integral
  381.      * @param y second symmetric variable of the integral
  382.      * @param z third symmetric variable of the integral
  383.      * @param <T> type of the field elements
  384.      * @return Carlson elliptic integral R<sub>D</sub>
  385.      */
  386.     public static <T extends CalculusFieldElement<T>> T rD(final T x, final T y, final T z) {
  387.         return new RdFieldDuplication<>(x, y, z).integral();
  388.     }

  389.     /** Compute Carlson elliptic integral R<sub>D</sub>.
  390.      * <p>
  391.      * The Carlson elliptic integral R<sub>D</sub> is defined as
  392.      * \[
  393.      *   R_D(x,y,z)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+z)}
  394.      * \]
  395.      * </p>
  396.      * @param x first symmetric variable of the integral
  397.      * @param y second symmetric variable of the integral
  398.      * @param z third symmetric variable of the integral
  399.      * @return Carlson elliptic integral R<sub>D</sub>
  400.      */
  401.     public static Complex rD(final Complex x, final Complex y, final Complex z) {
  402.         return new RdFieldDuplication<>(x, y, z).integral();
  403.     }

  404.     /** Compute Carlson elliptic integral R<sub>D</sub>.
  405.      * <p>
  406.      * The Carlson elliptic integral R<sub>D</sub> is defined as
  407.      * \[
  408.      *   R_D(x,y,z)=\frac{3}{2}\int_{0}^{\infty}\frac{\mathrm{d}t}{\sqrt{t+x}\sqrt{t+y}\sqrt{t+z}(t+z)}
  409.      * \]
  410.      * </p>
  411.      * @param x first symmetric variable of the integral
  412.      * @param y second symmetric variable of the integral
  413.      * @param z third symmetric variable of the integral
  414.      * @param <T> type of the field elements
  415.      * @return Carlson elliptic integral R<sub>D</sub>
  416.      */
  417.     public static <T extends CalculusFieldElement<T>> FieldComplex<T> rD(final FieldComplex<T> x, final FieldComplex<T> y,
  418.                                                                          final FieldComplex<T> z) {
  419.         return new RdFieldDuplication<>(x, y, z).integral();
  420.     }

  421.     /** Compute Carlson elliptic integral R<sub>G</sub>.
  422.      * <p>
  423.      * The Carlson elliptic integral R<sub>G</sub>is defined as
  424.      * \[
  425.      *   R_{G}(x,y,z)=\frac{1}{4}\int_{0}^{\infty}\frac{1}{s(t)}
  426.      *                \left(\frac{x}{t+x}+\frac{y}{t+y}+\frac{z}{t+z}\right)t\mathrm{d}t
  427.      * \]
  428.      * </p>
  429.      * @param x first symmetric variable of the integral
  430.      * @param y second symmetric variable of the integral
  431.      * @param z second symmetric variable of the integral
  432.      * @return Carlson elliptic integral R<sub>G</sub>
  433.      */
  434.     public static double rG(final double x, final double y, final double z) {
  435.         return generalComputeRg(x, y, z);
  436.     }

  437.     /** Compute Carlson elliptic integral R<sub>G</sub>.
  438.      * <p>
  439.      * The Carlson elliptic integral R<sub>G</sub>is defined as
  440.      * \[
  441.      *   R_{G}(x,y,z)=\frac{1}{4}\int_{0}^{\infty}\frac{1}{s(t)}
  442.      *                \left(\frac{x}{t+x}+\frac{y}{t+y}+\frac{z}{t+z}\right)t\mathrm{d}t
  443.      * \]
  444.      * </p>
  445.      * @param x first symmetric variable of the integral
  446.      * @param y second symmetric variable of the integral
  447.      * @param z second symmetric variable of the integral
  448.      * @param <T> type of the field elements
  449.      * @return Carlson elliptic integral R<sub>G</sub>
  450.      */
  451.     public static <T extends CalculusFieldElement<T>> T rG(final T x, final T y, final T z) {
  452.         return generalComputeRg(x, y, z);
  453.     }

  454.     /** Compute Carlson elliptic integral R<sub>G</sub>.
  455.      * <p>
  456.      * The Carlson elliptic integral R<sub>G</sub>is defined as
  457.      * \[
  458.      *   R_{G}(x,y,z)=\frac{1}{4}\int_{0}^{\infty}\frac{1}{s(t)}
  459.      *                \left(\frac{x}{t+x}+\frac{y}{t+y}+\frac{z}{t+z}\right)t\mathrm{d}t
  460.      * \]
  461.      * </p>
  462.      * @param x first symmetric variable of the integral
  463.      * @param y second symmetric variable of the integral
  464.      * @param z second symmetric variable of the integral
  465.      * @return Carlson elliptic integral R<sub>G</sub>
  466.      */
  467.     public static Complex rG(final Complex x, final Complex y, final Complex z) {
  468.         return generalComputeRg(x, y, z);
  469.     }

  470.     /** Compute Carlson elliptic integral R<sub>G</sub>.
  471.      * <p>
  472.      * The Carlson elliptic integral R<sub>G</sub>is defined as
  473.      * \[
  474.      *   R_{G}(x,y,z)=\frac{1}{4}\int_{0}^{\infty}\frac{1}{s(t)}
  475.      *                \left(\frac{x}{t+x}+\frac{y}{t+y}+\frac{z}{t+z}\right)t\mathrm{d}t
  476.      * \]
  477.      * </p>
  478.      * @param x first symmetric variable of the integral
  479.      * @param y second symmetric variable of the integral
  480.      * @param z second symmetric variable of the integral
  481.      * @param <T> type of the field elements
  482.      * @return Carlson elliptic integral R<sub>G</sub>
  483.      */
  484.     public static <T extends CalculusFieldElement<T>> FieldComplex<T> rG(final FieldComplex<T> x,
  485.                                                                          final FieldComplex<T> y,
  486.                                                                          final FieldComplex<T> z) {
  487.         return generalComputeRg(x, y, z);
  488.     }

  489.     /** Compute Carlson elliptic integral R<sub>G</sub> in the general case.
  490.      * @param x first symmetric variable of the integral
  491.      * @param y second symmetric variable of the integral
  492.      * @param z third symmetric variable of the integral
  493.      * @return Carlson elliptic integral R<sub>G</sub>
  494.      */
  495.     private static double generalComputeRg(final double x, final double y, final double z) {
  496.         // permute parameters if needed to avoid cancellations
  497.         if (x <= y) {
  498.             if (y <= z) {
  499.                 // x ≤ y ≤ z
  500.                 return permutedComputeRg(x, z, y);
  501.             } else if (x <= z) {
  502.                 // x ≤ z < y
  503.                 return permutedComputeRg(x, y, z);
  504.             } else {
  505.                 // z < x ≤ y
  506.                 return permutedComputeRg(z, y, x);
  507.             }
  508.         } else if (x <= z) {
  509.             // y < x ≤ z
  510.             return permutedComputeRg(y, z, x);
  511.         } else if (y <= z) {
  512.             // y ≤ z < x
  513.             return permutedComputeRg(y, x, z);
  514.         } else {
  515.             // z < y < x
  516.             return permutedComputeRg(z, x, y);
  517.         }
  518.     }

  519.     /** Compute Carlson elliptic integral R<sub>G</sub> in the general case.
  520.      * @param x first symmetric variable of the integral
  521.      * @param y second symmetric variable of the integral
  522.      * @param z third symmetric variable of the integral
  523.      * @param <T> type of the field elements (really {@link Complex} or {@link FieldComplex})
  524.      * @return Carlson elliptic integral R<sub>G</sub>
  525.      */
  526.     private static <T extends CalculusFieldElement<T>> T generalComputeRg(final T x, final T y, final T z) {
  527.         // permute parameters if needed to avoid cancellations
  528.         final double xR = x.getReal();
  529.         final double yR = y.getReal();
  530.         final double zR = z.getReal();
  531.         if (xR <= yR) {
  532.             if (yR <= zR) {
  533.                 // x ≤ y ≤ z
  534.                 return permutedComputeRg(x, z, y);
  535.             } else if (xR <= zR) {
  536.                 // x ≤ z < y
  537.                 return permutedComputeRg(x, y, z);
  538.             } else {
  539.                 // z < x ≤ y
  540.                 return permutedComputeRg(z, y, x);
  541.             }
  542.         } else if (xR <= zR) {
  543.             // y < x ≤ z
  544.             return permutedComputeRg(y, z, x);
  545.         } else if (yR <= zR) {
  546.             // y ≤ z < x
  547.             return permutedComputeRg(y, x, z);
  548.         } else {
  549.             // z < y < x
  550.             return permutedComputeRg(z, x, y);
  551.         }
  552.     }

  553.     /** Compute Carlson elliptic integral R<sub>G</sub> with already permuted variables to avoid cancellations.
  554.      * @param x first symmetric variable of the integral
  555.      * @param y second symmetric variable of the integral
  556.      * @param z third symmetric variable of the integral
  557.      * @return Carlson elliptic integral R<sub>G</sub>
  558.      */
  559.     private static double permutedComputeRg(final double x, final double y, final double z) {
  560.         // permute parameters if needed to avoid divisions by zero
  561.         if (z == 0) {
  562.             return x == 0 ? safeComputeRg(z, x, y) : safeComputeRg(y, z, x);
  563.         } else {
  564.             return safeComputeRg(x, y, z);
  565.         }
  566.     }

  567.     /** Compute Carlson elliptic integral R<sub>G</sub> with already permuted variables to avoid cancellations.
  568.      * @param x first symmetric variable of the integral
  569.      * @param y second symmetric variable of the integral
  570.      * @param z third symmetric variable of the integral
  571.      * @param <T> type of the field elements (really {@link Complex} or {@link FieldComplex})
  572.      * @return Carlson elliptic integral R<sub>G</sub>
  573.      */
  574.     private static <T extends CalculusFieldElement<T>> T permutedComputeRg(final T x, final T y, final T z) {
  575.         // permute parameters if needed to avoid divisions by zero
  576.         if (z.isZero()) {
  577.             return x.isZero() ? safeComputeRg(z, x, y) : safeComputeRg(y, z, x);
  578.         } else {
  579.             return safeComputeRg(x, y, z);
  580.         }
  581.     }

  582.     /** Compute Carlson elliptic integral R<sub>G</sub> with non-zero third variable.
  583.      * @param x first symmetric variable of the integral
  584.      * @param y second symmetric variable of the integral
  585.      * @param z third symmetric variable of the integral
  586.      * @see <a href="https://dlmf.nist.gov/19.21#E10">Digital Library of Mathematical Functions, equation 19.21.10</a>
  587.      * @return Carlson elliptic integral R<sub>G</sub>
  588.      */
  589.     private static double safeComputeRg(final double x, final double y, final double z) {

  590.         // contribution of the R_F integral
  591.         final double termF = new RfRealDuplication(x, y, z).integral() * z;

  592.         // contribution of the R_D integral
  593.         final double termD = (x - z) * (y - z) * new RdRealDuplication(x, y, z).integral() / 3;

  594.         // contribution of the square roots
  595.         final double termS = FastMath.sqrt(x * y / z);

  596.         // equation 19.21.10
  597.         return (termF - termD + termS) * 0.5;

  598.     }

  599.     /** Compute Carlson elliptic integral R<sub>G</sub> with non-zero third variable.
  600.      * @param x first symmetric variable of the integral
  601.      * @param y second symmetric variable of the integral
  602.      * @param z third symmetric variable of the integral
  603.      * @param <T> type of the field elements (really {@link Complex} or {@link FieldComplex})
  604.      * @see <a href="https://dlmf.nist.gov/19.21#E10">Digital Library of Mathematical Functions, equation 19.21.10</a>
  605.      * @return Carlson elliptic integral R<sub>G</sub>
  606.      */
  607.     private static <T extends CalculusFieldElement<T>> T safeComputeRg(final T x, final T y, final T z) {

  608.         // contribution of the R_F integral
  609.         final T termF = new RfFieldDuplication<>(x, y, z).integral().multiply(z);

  610.         // contribution of the R_D integral
  611.         final T termD = x.subtract(z).multiply(y.subtract(z)).multiply(new RdFieldDuplication<>(x, y, z).integral()).divide(3);

  612.         // contribution of the square roots
  613.         // BEWARE: this term MUST be computed as √x√y/√z with all square roots selected with positive real part
  614.         // and NOT as √(xy/z), otherwise sign errors may occur
  615.         final T termS = x.sqrt().multiply(y.sqrt()).divide(z.sqrt());

  616.         // equation 19.21.10
  617.         return termF.subtract(termD).add(termS).multiply(0.5);

  618.     }

  619. }