FieldComplexParameter.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.CalculusFieldElement;
  19. import org.hipparchus.complex.FieldComplex;
  20. import org.hipparchus.special.elliptic.legendre.LegendreEllipticIntegral;
  21. import org.hipparchus.util.FastMath;

  22. /** Algorithm for computing the principal Jacobi functions for complex parameter m.
  23.  * @param <T> the type of the field elements
  24.  * @since 2.0
  25.  */
  26. class FieldComplexParameter<T extends CalculusFieldElement<T>> extends FieldJacobiElliptic<FieldComplex<T>> {

  27.     /** Jacobi θ functions. */
  28.     private final FieldJacobiTheta<FieldComplex<T>> jacobiTheta;

  29.     /** Quarter period K. */
  30.     private final FieldComplex<T> bigK;

  31.     /** Quarter period iK'. */
  32.     private final FieldComplex<T> iBigKPrime;

  33.     /** Real periodic factor for K. */
  34.     private final T rK;

  35.     /** Imaginary periodic factor for K. */
  36.     private final T iK;

  37.     /** Real periodic factor for iK'. */
  38.     private final T rKPrime;

  39.     /** Imaginary periodic factor for iK'. */
  40.     private final T iKPrime;

  41.     /** Value of Jacobi θ functions at origin. */
  42.     private final FieldTheta<FieldComplex<T>> t0;

  43.     /** Scaling factor. */
  44.     private final FieldComplex<T> scaling;

  45.     /** Simple constructor.
  46.      * @param m parameter of the Jacobi elliptic function
  47.      */
  48.     FieldComplexParameter(final FieldComplex<T> m) {

  49.         super(m);

  50.         // compute nome
  51.          final FieldComplex<T> q = LegendreEllipticIntegral.nome(m);

  52.         // compute periodic factors such that
  53.         // z = 4K [rK Re(z) + iK Im(z)] + 4K' [rK' Re(z) + iK' Im(z)]
  54.         bigK            = LegendreEllipticIntegral.bigK(m);
  55.         iBigKPrime      = LegendreEllipticIntegral.bigKPrime(m).multiplyPlusI();
  56.         final T inverse = bigK.getRealPart().multiply(iBigKPrime.getImaginaryPart()).
  57.                           subtract(bigK.getImaginaryPart().multiply(iBigKPrime.getRealPart())).
  58.                           multiply(4).reciprocal();
  59.         this.rK         = iBigKPrime.getImaginaryPart().multiply(inverse);
  60.         this.iK         = iBigKPrime.getRealPart().multiply(inverse).negate();
  61.         this.rKPrime    = bigK.getImaginaryPart().multiply(inverse).negate();
  62.         this.iKPrime    = bigK.getRealPart().multiply(inverse);

  63.         // prepare underlying Jacobi θ functions
  64.         this.jacobiTheta = new FieldJacobiTheta<>(q);
  65.         this.t0          = jacobiTheta.values(m.getField().getZero());
  66.         this.scaling     = bigK.reciprocal().multiply(m.getPi().multiply(0.5));

  67.     }

  68.     /** {@inheritDoc}
  69.      * <p>
  70.      * The algorithm for evaluating the functions is based on {@link FieldJacobiTheta
  71.      * Jacobi theta functions}.
  72.      * </p>
  73.      */
  74.     @Override
  75.     public FieldCopolarN<FieldComplex<T>> valuesN(FieldComplex<T> u) {

  76.         // perform argument reduction
  77.         final T cK      = rK.multiply(u.getRealPart()).add(iK.multiply(u.getImaginaryPart()));
  78.         final T cKPrime = rKPrime.multiply(u.getRealPart()).add(iKPrime.multiply(u.getImaginaryPart()));
  79.         final FieldComplex<T> reducedU = u.linearCombination(1.0,                                  u,
  80.                                                             -4 * FastMath.rint(cK.getReal()),      bigK,
  81.                                                             -4 * FastMath.rint(cKPrime.getReal()), iBigKPrime);

  82.         // evaluate Jacobi θ functions at argument
  83.         final FieldTheta<FieldComplex<T>> tZ = jacobiTheta.values(reducedU.multiply(scaling));

  84.         // convert to Jacobi elliptic functions
  85.         final FieldComplex<T> sn = t0.theta3().multiply(tZ.theta1()).divide(t0.theta2().multiply(tZ.theta4()));
  86.         final FieldComplex<T> cn = t0.theta4().multiply(tZ.theta2()).divide(t0.theta2().multiply(tZ.theta4()));
  87.         final FieldComplex<T> dn = t0.theta4().multiply(tZ.theta3()).divide(t0.theta3().multiply(tZ.theta4()));

  88.         return new FieldCopolarN<>(sn, cn, dn);

  89.     }

  90. }