RjRealDuplication.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.util.FastMath;
  19. import org.hipparchus.util.MathArrays;

  20. /** Duplication algorithm for Carlson R<sub>J</sub> elliptic integral.
  21.  * @since 2.0
  22.  */
  23. class RjRealDuplication extends RealDuplication {

  24.     /** Delta product. */
  25.     private double delta;

  26.     /** sₘ iteration parameter. */
  27.     private double sM;

  28.     /** Simple constructor.
  29.      * @param x first symmetric variable of the integral
  30.      * @param y second symmetric variable of the integral
  31.      * @param z third symmetric variable of the integral
  32.      * @param p fourth <em>not</em> symmetric variable of the integral
  33.      * @param delta precomputed value of (p-x)(p-y)(p-z)
  34.      */
  35.     RjRealDuplication(final double x, final double y, final double z, final double p, final double delta) {
  36.         super(x, y, z, p);
  37.         this.delta = delta;
  38.     }

  39.     /** {@inheritDoc} */
  40.     @Override
  41.     protected void initialMeanPoint(final double[] va) {
  42.         va[4] = (va[0] + va[1] + va[2] + va[3] * 2) / 5.0;
  43.     }

  44.     /** {@inheritDoc} */
  45.     @Override
  46.     protected double convergenceCriterion(final double r, final double max) {
  47.         return max / (FastMath.sqrt(FastMath.sqrt(FastMath.sqrt(r * 0.25))));
  48.     }

  49.     /** {@inheritDoc} */
  50.     @Override
  51.     protected void update(final int m, final double[] vaM, final double[] sqrtM, final  double fourM) {
  52.         final double dM = (sqrtM[3] + sqrtM[0]) * (sqrtM[3] + sqrtM[1]) * (sqrtM[3] + sqrtM[2]);
  53.         if (m == 0) {
  54.             sM = dM * 0.5;
  55.         } else {
  56.             // equation A.3 in Carlson[2000]
  57.             final double rM = sM * (FastMath.sqrt(delta / (sM * sM * fourM) + 1.0) + 1.0);
  58.             sM = (dM * rM - delta / (fourM * fourM)) / ((dM + rM / fourM) * 2);
  59.         }

  60.         // equation 2.19 in Carlson[1995]
  61.         final double lambdaA = sqrtM[0] * sqrtM[1];
  62.         final double lambdaB = sqrtM[0] * sqrtM[2];
  63.         final double lambdaC = sqrtM[1] * sqrtM[2];

  64.         // equations 2.19 and 2.20 in Carlson[1995]
  65.         vaM[0] = MathArrays.linearCombination(0.25, vaM[0], 0.25, lambdaA, 0.25, lambdaB, 0.25, lambdaC); // xₘ
  66.         vaM[1] = MathArrays.linearCombination(0.25, vaM[1], 0.25, lambdaA, 0.25, lambdaB, 0.25, lambdaC); // yₘ
  67.         vaM[2] = MathArrays.linearCombination(0.25, vaM[2], 0.25, lambdaA, 0.25, lambdaB, 0.25, lambdaC); // zₘ
  68.         vaM[3] = MathArrays.linearCombination(0.25, vaM[3], 0.25, lambdaA, 0.25, lambdaB, 0.25, lambdaC); // pₘ
  69.         vaM[4] = MathArrays.linearCombination(0.25, vaM[4], 0.25, lambdaA, 0.25, lambdaB, 0.25, lambdaC); // aₘ

  70.     }

  71.     /** {@inheritDoc} */
  72.     @Override
  73.     protected double evaluate(final double[] va0, final double aM, final  double fourM) {

  74.         // compute symmetric differences
  75.         final double inv    = 1.0 / (aM * fourM);
  76.         final double bigX   = (va0[4] - va0[0]) * inv;
  77.         final double bigY   = (va0[4] - va0[1]) * inv;
  78.         final double bigZ   = (va0[4] - va0[2]) * inv;
  79.         final double bigP   = (bigX + bigY + bigZ) * -0.5;
  80.         final double bigP2  = bigP * bigP;

  81.         // compute elementary symmetric functions (we already know e1 = 0 by construction)
  82.         final double xyz    = bigX * bigY * bigZ;
  83.         final double e2     = bigX * (bigY + bigZ) + bigY * bigZ - bigP * bigP * 3;
  84.         final double e3     = xyz + bigP * 2 * (e2 + bigP2 * 2);
  85.         final double e4     = (xyz * 2 + bigP * (e2 + bigP2 * 3)) * bigP;
  86.         final double e5     = xyz * bigP2;

  87.         final double e2e2   = e2   * e2;
  88.         final double e2e3   = e2   * e3;
  89.         final double e2e4   = e2   * e4;
  90.         final double e2e5   = e2   * e5;
  91.         final double e3e3   = e3   * e3;
  92.         final double e3e4   = e3   * e4;
  93.         final double e2e2e2 = e2e2 * e2;
  94.         final double e2e2e3 = e2e2 * e3;

  95.         // evaluate integral using equation 19.36.1 in DLMF
  96.         // (which add more terms than equation 2.7 in Carlson[1995])
  97.         final double poly = ((e3e4 + e2e5) * RdRealDuplication.E3_E4_P_E2_E5 +
  98.                               e2e2e3       * RdRealDuplication.E2_E2_E3 +
  99.                               e2e4         * RdRealDuplication.E2_E4 +
  100.                               e3e3         * RdRealDuplication.E3_E3 +
  101.                               e2e2e2       * RdRealDuplication.E2_E2_E2 +
  102.                               e5           * RdRealDuplication.E5 +
  103.                               e2e3         * RdRealDuplication.E2_E3 +
  104.                               e4           * RdRealDuplication.E4 +
  105.                               e2e2         * RdRealDuplication.E2_E2 +
  106.                               e3           * RdRealDuplication.E3 +
  107.                               e2           * RdRealDuplication.E2 +
  108.                               RdRealDuplication.CONSTANT) /
  109.                              RdRealDuplication.DENOMINATOR;
  110.         final double polyTerm = poly / (aM * FastMath.sqrt(aM) * fourM);

  111.         // compute a single R_C term
  112.         final double rcTerm = new RcRealDuplication(1.0, delta / (sM * sM * fourM) + 1.0).integral() * 3 / sM;

  113.         return polyTerm + rcTerm;

  114.     }

  115. }