FieldUnivariateDerivative1.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.analysis.differentiation;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.Field;
  20. import org.hipparchus.exception.LocalizedCoreFormats;
  21. import org.hipparchus.exception.MathIllegalArgumentException;
  22. import org.hipparchus.util.FastMath;
  23. import org.hipparchus.util.MathArrays;
  24. import org.hipparchus.util.MathUtils;

  25. /** Class representing both the value and the differentials of a function.
  26.  * <p>This class is a stripped-down version of {@link FieldDerivativeStructure}
  27.  * with only one {@link FieldDerivativeStructure#getFreeParameters() free parameter}
  28.  * and {@link FieldDerivativeStructure#getOrder() derivation order} also limited to one.
  29.  * It should have less overhead than {@link FieldDerivativeStructure} in its domain.</p>
  30.  * <p>This class is an implementation of Rall's numbers. Rall's numbers are an
  31.  * extension to the real numbers used throughout mathematical expressions; they hold
  32.  * the derivative together with the value of a function.</p>
  33.  * <p>{@link FieldUnivariateDerivative1} instances can be used directly thanks to
  34.  * the arithmetic operators to the mathematical functions provided as
  35.  * methods by this class (+, -, *, /, %, sin, cos ...).</p>
  36.  * <p>Implementing complex expressions by hand using {@link Derivative}-based
  37.  * classes (or in fact any {@link org.hipparchus.CalculusFieldElement} class) is
  38.  * a tedious and error-prone task but has the advantage of not requiring users
  39.  * to compute the derivatives by themselves and allowing to switch for one
  40.  * derivative implementation to another as they all share the same filed API.</p>
  41.  * <p>Instances of this class are guaranteed to be immutable.</p>
  42.  * @param <T> the type of the function parameters and value
  43.  * @see DerivativeStructure
  44.  * @see UnivariateDerivative1
  45.  * @see UnivariateDerivative2
  46.  * @see Gradient
  47.  * @see FieldDerivativeStructure
  48.  * @see FieldUnivariateDerivative2
  49.  * @see FieldGradient
  50.  * @since 1.7
  51.  */
  52. public class FieldUnivariateDerivative1<T extends CalculusFieldElement<T>>
  53.     extends FieldUnivariateDerivative<T, FieldUnivariateDerivative1<T>>
  54.         implements FieldDerivative1<T, FieldUnivariateDerivative1<T>> {

  55.     /** Value of the function. */
  56.     private final T f0;

  57.     /** First derivative of the function. */
  58.     private final T f1;

  59.     /** Build an instance with values and derivative.
  60.      * @param f0 value of the function
  61.      * @param f1 first derivative of the function
  62.      */
  63.     public FieldUnivariateDerivative1(final T f0, final T f1) {
  64.         this.f0 = f0;
  65.         this.f1 = f1;
  66.     }

  67.     /** Build an instance from a {@link FieldDerivativeStructure}.
  68.      * @param ds derivative structure
  69.      * @exception MathIllegalArgumentException if either {@code ds} parameters
  70.      * is not 1 or {@code ds} order is not 1
  71.      */
  72.     public FieldUnivariateDerivative1(final FieldDerivativeStructure<T> ds) throws MathIllegalArgumentException {
  73.         MathUtils.checkDimension(ds.getFreeParameters(), 1);
  74.         MathUtils.checkDimension(ds.getOrder(), 1);
  75.         this.f0 = ds.getValue();
  76.         this.f1 = ds.getPartialDerivative(1);
  77.     }

  78.     /** {@inheritDoc} */
  79.     @Override
  80.     public FieldUnivariateDerivative1<T> newInstance(final double value) {
  81.         final T zero = f0.getField().getZero();
  82.         return new FieldUnivariateDerivative1<>(zero.newInstance(value), zero);
  83.     }

  84.     /** {@inheritDoc} */
  85.     @Override
  86.     public FieldUnivariateDerivative1<T> newInstance(final T value) {
  87.         final T zero = f0.getField().getZero();
  88.         return new FieldUnivariateDerivative1<>(value, zero);
  89.     }

  90.     /** {@inheritDoc} */
  91.     @Override
  92.     public FieldUnivariateDerivative1<T> withValue(final T value) {
  93.         return new FieldUnivariateDerivative1<>(value, f1);
  94.     }

  95.     /** {@inheritDoc} */
  96.     @Override
  97.     public FieldUnivariateDerivative1<T> getAddendum() {
  98.         return new FieldUnivariateDerivative1<>(f0.getField().getZero(), f1);
  99.     }

  100.     /** Get the value part of the univariate derivative.
  101.      * @return value part of the univariate derivative
  102.      */
  103.     @Override
  104.     public T getValue() {
  105.         return f0;
  106.     }

  107.     /** Get a derivative from the univariate derivative.
  108.      * @param n derivation order (must be between 0 and {@link #getOrder()}, both inclusive)
  109.      * @return n<sup>th</sup> derivative, or {@code NaN} if n is
  110.      * either negative or strictly larger than {@link #getOrder()}
  111.      */
  112.     @Override
  113.     public T getDerivative(final int n) {
  114.         switch (n) {
  115.             case 0 :
  116.                 return f0;
  117.             case 1 :
  118.                 return f1;
  119.             default :
  120.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DERIVATION_ORDER_NOT_ALLOWED, n);
  121.         }
  122.     }

  123.     /** Get the first derivative.
  124.      * @return first derivative
  125.      * @see #getValue()
  126.      */
  127.     public T getFirstDerivative() {
  128.         return f1;
  129.     }

  130.     /** Get the {@link Field} the value and parameters of the function belongs to.
  131.      * @return {@link Field} the value and parameters of the function belongs to
  132.      */
  133.     public Field<T> getValueField() {
  134.         return f0.getField();
  135.     }

  136.     /** Convert the instance to a {@link FieldDerivativeStructure}.
  137.      * @return derivative structure with same value and derivative as the instance
  138.      */
  139.     @Override
  140.     public FieldDerivativeStructure<T> toDerivativeStructure() {
  141.         return getField().getConversionFactory().build(f0, f1);
  142.     }

  143.     /** {@inheritDoc} */
  144.     @Override
  145.     public FieldUnivariateDerivative1<T> add(final double a) {
  146.         return new FieldUnivariateDerivative1<>(f0.add(a), f1);
  147.     }

  148.     /** {@inheritDoc} */
  149.     @Override
  150.     public FieldUnivariateDerivative1<T> add(final FieldUnivariateDerivative1<T> a) {
  151.         return new FieldUnivariateDerivative1<>(f0.add(a.f0), f1.add(a.f1));
  152.     }

  153.     /** {@inheritDoc} */
  154.     @Override
  155.     public FieldUnivariateDerivative1<T> subtract(final double a) {
  156.         return new FieldUnivariateDerivative1<>(f0.subtract(a), f1);
  157.     }

  158.     /** {@inheritDoc} */
  159.     @Override
  160.     public FieldUnivariateDerivative1<T> subtract(final FieldUnivariateDerivative1<T> a) {
  161.         return new FieldUnivariateDerivative1<>(f0.subtract(a.f0), f1.subtract(a.f1));
  162.     }

  163.     /** '&times;' operator.
  164.      * @param a right hand side parameter of the operator
  165.      * @return this&times;a
  166.      */
  167.     public FieldUnivariateDerivative1<T> multiply(final T a) {
  168.         return new FieldUnivariateDerivative1<>(f0.multiply(a), f1.multiply(a));
  169.     }

  170.     /** {@inheritDoc} */
  171.     @Override
  172.     public FieldUnivariateDerivative1<T> multiply(final int n) {
  173.         return new FieldUnivariateDerivative1<>(f0.multiply(n), f1.multiply(n));
  174.     }

  175.     /** {@inheritDoc} */
  176.     @Override
  177.     public FieldUnivariateDerivative1<T> multiply(final double a) {
  178.         return new FieldUnivariateDerivative1<>(f0.multiply(a), f1.multiply(a));
  179.     }

  180.     /** {@inheritDoc} */
  181.     @Override
  182.     public FieldUnivariateDerivative1<T> multiply(final FieldUnivariateDerivative1<T> a) {
  183.         return new FieldUnivariateDerivative1<>(f0.multiply(a.f0),
  184.                                                 a.f0.linearCombination(f1, a.f0, f0, a.f1));
  185.     }

  186.     /** '&divide;' operator.
  187.      * @param a right hand side parameter of the operator
  188.      * @return this&divide;a
  189.      */
  190.     public FieldUnivariateDerivative1<T> divide(final T a) {
  191.         final T inv1 = a.reciprocal();
  192.         return new FieldUnivariateDerivative1<>(f0.multiply(inv1), f1.multiply(inv1));
  193.     }

  194.     /** {@inheritDoc} */
  195.     @Override
  196.     public FieldUnivariateDerivative1<T> divide(final double a) {
  197.         final double inv1 = 1.0 / a;
  198.         return new FieldUnivariateDerivative1<>(f0.multiply(inv1), f1.multiply(inv1));
  199.     }

  200.     /** {@inheritDoc} */
  201.     @Override
  202.     public FieldUnivariateDerivative1<T> divide(final FieldUnivariateDerivative1<T> a) {
  203.         final T inv1 = a.f0.reciprocal();
  204.         final T inv2 = inv1.multiply(inv1);
  205.         return new FieldUnivariateDerivative1<>(f0.multiply(inv1),
  206.                                                 a.f0.linearCombination(f1, a.f0, f0.negate(), a.f1).multiply(inv2));
  207.     }

  208.     /** IEEE remainder operator.
  209.      * @param a right hand side parameter of the operator
  210.      * @return this - n &times; a where n is the closest integer to this/a
  211.      * (the even integer is chosen for n if this/a is halfway between two integers)
  212.      */
  213.     public FieldUnivariateDerivative1<T> remainder(final T a) {
  214.         return new FieldUnivariateDerivative1<>(FastMath.IEEEremainder(f0, a), f1);
  215.     }

  216.     /** {@inheritDoc} */
  217.     @Override
  218.     public FieldUnivariateDerivative1<T> remainder(final double a) {
  219.         return new FieldUnivariateDerivative1<>(FastMath.IEEEremainder(f0, a), f1);
  220.     }

  221.     /** {@inheritDoc} */
  222.     @Override
  223.     public FieldUnivariateDerivative1<T> remainder(final FieldUnivariateDerivative1<T> a) {

  224.         // compute k such that lhs % rhs = lhs - k rhs
  225.         final T rem = FastMath.IEEEremainder(f0, a.f0);
  226.         final T k   = FastMath.rint(f0.subtract(rem).divide(a.f0));

  227.         return new FieldUnivariateDerivative1<>(rem, f1.subtract(k.multiply(a.f1)));

  228.     }

  229.     /** {@inheritDoc} */
  230.     @Override
  231.     public FieldUnivariateDerivative1<T> negate() {
  232.         return new FieldUnivariateDerivative1<>(f0.negate(), f1.negate());
  233.     }

  234.     /** {@inheritDoc} */
  235.     @Override
  236.     public FieldUnivariateDerivative1<T> abs() {
  237.         if (Double.doubleToLongBits(f0.getReal()) < 0) {
  238.             // we use the bits representation to also handle -0.0
  239.             return negate();
  240.         } else {
  241.             return this;
  242.         }
  243.     }

  244.     /**
  245.      * Returns the instance with the sign of the argument.
  246.      * A NaN {@code sign} argument is treated as positive.
  247.      *
  248.      * @param sign the sign for the returned value
  249.      * @return the instance with the same sign as the {@code sign} argument
  250.      */
  251.     public FieldUnivariateDerivative1<T> copySign(final T sign) {
  252.         long m = Double.doubleToLongBits(f0.getReal());
  253.         long s = Double.doubleToLongBits(sign.getReal());
  254.         if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
  255.             return this;
  256.         }
  257.         return negate(); // flip sign
  258.     }

  259.     /** {@inheritDoc} */
  260.     @Override
  261.     public FieldUnivariateDerivative1<T> copySign(final FieldUnivariateDerivative1<T> sign) {
  262.         long m = Double.doubleToLongBits(f0.getReal());
  263.         long s = Double.doubleToLongBits(sign.f0.getReal());
  264.         if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
  265.             return this;
  266.         }
  267.         return negate(); // flip sign
  268.     }

  269.     /** {@inheritDoc} */
  270.     @Override
  271.     public FieldUnivariateDerivative1<T> copySign(final double sign) {
  272.         long m = Double.doubleToLongBits(f0.getReal());
  273.         long s = Double.doubleToLongBits(sign);
  274.         if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
  275.             return this;
  276.         }
  277.         return negate(); // flip sign
  278.     }

  279.     /** {@inheritDoc} */
  280.     @Override
  281.     public FieldUnivariateDerivative1<T> scalb(final int n) {
  282.         return new FieldUnivariateDerivative1<>(FastMath.scalb(f0, n), FastMath.scalb(f1, n));
  283.     }

  284.     /** {@inheritDoc} */
  285.     @Override
  286.     public FieldUnivariateDerivative1<T> hypot(final FieldUnivariateDerivative1<T> y) {

  287.         if (Double.isInfinite(f0.getReal()) || Double.isInfinite(y.f0.getReal())) {
  288.             return new FieldUnivariateDerivative1<>(f0.newInstance(Double.POSITIVE_INFINITY),
  289.                                                     f0.getField().getZero());
  290.         } else if (Double.isNaN(f0.getReal()) || Double.isNaN(y.f0.getReal())) {
  291.             return new FieldUnivariateDerivative1<>(f0.newInstance(Double.NaN),
  292.                                                     f0.getField().getZero());
  293.         } else {

  294.             final int expX = getExponent();
  295.             final int expY = y.getExponent();
  296.             if (expX > expY + 27) {
  297.                 // y is negligible with respect to x
  298.                 return abs();
  299.             } else if (expY > expX + 27) {
  300.                 // x is negligible with respect to y
  301.                 return y.abs();
  302.             } else {

  303.                 // find an intermediate scale to avoid both overflow and underflow
  304.                 final int middleExp = (expX + expY) / 2;

  305.                 // scale parameters without losing precision
  306.                 final FieldUnivariateDerivative1<T> scaledX = scalb(-middleExp);
  307.                 final FieldUnivariateDerivative1<T> scaledY = y.scalb(-middleExp);

  308.                 // compute scaled hypotenuse
  309.                 final FieldUnivariateDerivative1<T> scaledH =
  310.                         scaledX.multiply(scaledX).add(scaledY.multiply(scaledY)).sqrt();

  311.                 // remove scaling
  312.                 return scaledH.scalb(middleExp);

  313.             }

  314.         }
  315.     }

  316.     /** Compute composition of the instance by a function.
  317.      * @param g0 value of the function at the current point (i.e. at {@code g(getValue())})
  318.      * @param g1 first derivative of the function at the current point (i.e. at {@code g'(getValue())})
  319.      * @return g(this)
  320.      */
  321.     @Override
  322.     public FieldUnivariateDerivative1<T> compose(final T g0, final T g1) {
  323.         return new FieldUnivariateDerivative1<>(g0, g1.multiply(f1));
  324.     }

  325.     /** {@inheritDoc} */
  326.     @Override
  327.     public FieldUnivariateDerivative1<T> rootN(final int n) {
  328.         if (n == 2) {
  329.             return sqrt();
  330.         } else if (n == 3) {
  331.             return cbrt();
  332.         } else {
  333.             final T r = FastMath.pow(f0, 1.0 / n);
  334.             return compose(r, FastMath.pow(r, n - 1).multiply(n).reciprocal());
  335.         }
  336.     }

  337.     /** {@inheritDoc} */
  338.     @Override
  339.     public FieldUnivariateDerivative1Field<T> getField() {
  340.         return FieldUnivariateDerivative1Field.getUnivariateDerivative1Field(f0.getField());
  341.     }

  342.     /** Compute a<sup>x</sup> where a is a double and x a {@link FieldUnivariateDerivative1}
  343.      * @param a number to exponentiate
  344.      * @param x power to apply
  345.      * @param <T> the type of the function parameters and value
  346.      * @return a<sup>x</sup>
  347.      */
  348.     public static <T extends CalculusFieldElement<T>> FieldUnivariateDerivative1<T> pow(final double a, final FieldUnivariateDerivative1<T> x) {
  349.         if (a == 0) {
  350.             return x.getField().getZero();
  351.         } else {
  352.             final T aX = FastMath.pow(x.f0.newInstance(a), x.f0);
  353.             return new FieldUnivariateDerivative1<>(aX, aX.multiply(FastMath.log(a)).multiply(x.f1));
  354.         }
  355.     }

  356.     /** {@inheritDoc} */
  357.     @Override
  358.     public FieldUnivariateDerivative1<T> pow(final double p) {
  359.         if (p == 0) {
  360.             return getField().getOne();
  361.         } else {
  362.             final T f0Pm1 = FastMath.pow(f0, p - 1);
  363.             return compose(f0Pm1.multiply(f0), f0Pm1.multiply(p));
  364.         }
  365.     }

  366.     /** {@inheritDoc} */
  367.     @Override
  368.     public FieldUnivariateDerivative1<T> pow(final int n) {
  369.         if (n == 0) {
  370.             return getField().getOne();
  371.         } else {
  372.             final T f0Nm1 = FastMath.pow(f0, n - 1);
  373.             return compose(f0Nm1.multiply(f0), f0Nm1.multiply(n));
  374.         }
  375.     }

  376.     /** {@inheritDoc} */
  377.     @Override
  378.     public FieldUnivariateDerivative1<T> atan2(final FieldUnivariateDerivative1<T> x) {
  379.         final T inv = f0.square().add(x.f0.multiply(x.f0)).reciprocal();
  380.         return new FieldUnivariateDerivative1<>(FastMath.atan2(f0, x.f0),
  381.                                                 f0.linearCombination(x.f0, f1, x.f1.negate(), f0).multiply(inv));
  382.     }

  383.     /** {@inheritDoc} */
  384.     @Override
  385.     public FieldUnivariateDerivative1<T> toDegrees() {
  386.         return new FieldUnivariateDerivative1<>(FastMath.toDegrees(f0), FastMath.toDegrees(f1));
  387.     }

  388.     /** {@inheritDoc} */
  389.     @Override
  390.     public FieldUnivariateDerivative1<T> toRadians() {
  391.         return new FieldUnivariateDerivative1<>(FastMath.toRadians(f0), FastMath.toRadians(f1));
  392.     }

  393.     /** Evaluate Taylor expansion of a univariate derivative.
  394.      * @param delta parameter offset Δx
  395.      * @return value of the Taylor expansion at x + Δx
  396.      */
  397.     public T taylor(final double delta) {
  398.         return f0.add(f1.multiply(delta));
  399.     }

  400.     /** Evaluate Taylor expansion of a univariate derivative.
  401.      * @param delta parameter offset Δx
  402.      * @return value of the Taylor expansion at x + Δx
  403.      */
  404.     public T taylor(final T delta) {
  405.         return f0.add(f1.multiply(delta));
  406.     }

  407.     /**
  408.      * Compute a linear combination.
  409.      * @param a Factors.
  410.      * @param b Factors.
  411.      * @return <code>&Sigma;<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>.
  412.      * @throws MathIllegalArgumentException if arrays dimensions don't match
  413.      */
  414.     public FieldUnivariateDerivative1<T> linearCombination(final T[] a, final FieldUnivariateDerivative1<T>[] b) {

  415.         // extract values and first derivatives
  416.         final Field<T> field = b[0].f0.getField();
  417.         final int      n  = b.length;
  418.         final T[] b0 = MathArrays.buildArray(field, n);
  419.         final T[] b1 = MathArrays.buildArray(field, n);
  420.         for (int i = 0; i < n; ++i) {
  421.             b0[i] = b[i].f0;
  422.             b1[i] = b[i].f1;
  423.         }

  424.         return new FieldUnivariateDerivative1<>(b[0].f0.linearCombination(a, b0),
  425.                                                 b[0].f0.linearCombination(a, b1));

  426.     }

  427.     /** {@inheritDoc} */
  428.     @Override
  429.     public FieldUnivariateDerivative1<T> linearCombination(final FieldUnivariateDerivative1<T>[] a,
  430.                                                            final FieldUnivariateDerivative1<T>[] b) {

  431.         // extract values and first derivatives
  432.         final Field<T> field = a[0].f0.getField();
  433.         final int n  = a.length;
  434.         final T[] a0 = MathArrays.buildArray(field, n);
  435.         final T[] b0 = MathArrays.buildArray(field, n);
  436.         final T[] a1 = MathArrays.buildArray(field, 2 * n);
  437.         final T[] b1 = MathArrays.buildArray(field, 2 * n);
  438.         for (int i = 0; i < n; ++i) {
  439.             final FieldUnivariateDerivative1<T> ai = a[i];
  440.             final FieldUnivariateDerivative1<T> bi = b[i];
  441.             a0[i]         = ai.f0;
  442.             b0[i]         = bi.f0;
  443.             a1[2 * i]     = ai.f0;
  444.             a1[2 * i + 1] = ai.f1;
  445.             b1[2 * i]     = bi.f1;
  446.             b1[2 * i + 1] = bi.f0;
  447.         }

  448.         return new FieldUnivariateDerivative1<>(a[0].f0.linearCombination(a0, b0),
  449.                                                 a[0].f0.linearCombination(a1, b1));

  450.     }

  451.     /** {@inheritDoc} */
  452.     @Override
  453.     public FieldUnivariateDerivative1<T> linearCombination(final double[] a, final FieldUnivariateDerivative1<T>[] b) {

  454.         // extract values and first derivatives
  455.         final Field<T> field = b[0].f0.getField();
  456.         final int      n  = b.length;
  457.         final T[] b0 = MathArrays.buildArray(field, n);
  458.         final T[] b1 = MathArrays.buildArray(field, n);
  459.         for (int i = 0; i < n; ++i) {
  460.             b0[i] = b[i].f0;
  461.             b1[i] = b[i].f1;
  462.         }

  463.         return new FieldUnivariateDerivative1<>(b[0].f0.linearCombination(a, b0),
  464.                                                 b[0].f0.linearCombination(a, b1));

  465.     }

  466.     /** {@inheritDoc} */
  467.     @Override
  468.     public FieldUnivariateDerivative1<T> linearCombination(final FieldUnivariateDerivative1<T> a1, final FieldUnivariateDerivative1<T> b1,
  469.                                                            final FieldUnivariateDerivative1<T> a2, final FieldUnivariateDerivative1<T> b2) {
  470.         return new FieldUnivariateDerivative1<>(a1.f0.linearCombination(a1.f0, b1.f0,
  471.                                                                         a2.f0, b2.f0),
  472.                                                 a1.f0.linearCombination(a1.f0, b1.f1,
  473.                                                                         a1.f1, b1.f0,
  474.                                                                         a2.f0, b2.f1,
  475.                                                                         a2.f1, b2.f0));
  476.     }

  477.     /** {@inheritDoc} */
  478.     @Override
  479.     public FieldUnivariateDerivative1<T> linearCombination(final double a1, final FieldUnivariateDerivative1<T> b1,
  480.                                                            final double a2, final FieldUnivariateDerivative1<T> b2) {
  481.         return new FieldUnivariateDerivative1<>(b1.f0.linearCombination(a1, b1.f0,
  482.                                                                         a2, b2.f0),
  483.                                                 b1.f0.linearCombination(a1, b1.f1,
  484.                                                                         a2, b2.f1));
  485.     }

  486.     /** {@inheritDoc} */
  487.     @Override
  488.     public FieldUnivariateDerivative1<T> linearCombination(final FieldUnivariateDerivative1<T> a1, final FieldUnivariateDerivative1<T> b1,
  489.                                                            final FieldUnivariateDerivative1<T> a2, final FieldUnivariateDerivative1<T> b2,
  490.                                                            final FieldUnivariateDerivative1<T> a3, final FieldUnivariateDerivative1<T> b3) {
  491.         final Field<T> field = a1.f0.getField();
  492.         final T[] a = MathArrays.buildArray(field, 6);
  493.         final T[] b = MathArrays.buildArray(field, 6);
  494.         a[0] = a1.f0;
  495.         a[1] = a1.f1;
  496.         a[2] = a2.f0;
  497.         a[3] = a2.f1;
  498.         a[4] = a3.f0;
  499.         a[5] = a3.f1;
  500.         b[0] = b1.f1;
  501.         b[1] = b1.f0;
  502.         b[2] = b2.f1;
  503.         b[3] = b2.f0;
  504.         b[4] = b3.f1;
  505.         b[5] = b3.f0;
  506.         return new FieldUnivariateDerivative1<>(a1.f0.linearCombination(a1.f0, b1.f0,
  507.                                                                         a2.f0, b2.f0,
  508.                                                                         a3.f0, b3.f0),
  509.                                                 a1.f0.linearCombination(a, b));
  510.     }

  511.     /**
  512.      * Compute a linear combination.
  513.      * @param a1 first factor of the first term
  514.      * @param b1 second factor of the first term
  515.      * @param a2 first factor of the second term
  516.      * @param b2 second factor of the second term
  517.      * @param a3 first factor of the third term
  518.      * @param b3 second factor of the third term
  519.      * @return a<sub>1</sub>&times;b<sub>1</sub> +
  520.      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
  521.      * @see #linearCombination(double, FieldUnivariateDerivative1, double, FieldUnivariateDerivative1)
  522.      * @see #linearCombination(double, FieldUnivariateDerivative1, double, FieldUnivariateDerivative1, double, FieldUnivariateDerivative1, double, FieldUnivariateDerivative1)
  523.      * @exception MathIllegalArgumentException if number of free parameters or orders are inconsistent
  524.      */
  525.     public FieldUnivariateDerivative1<T> linearCombination(final T a1, final FieldUnivariateDerivative1<T> b1,
  526.                                                            final T a2, final FieldUnivariateDerivative1<T> b2,
  527.                                                            final T a3, final FieldUnivariateDerivative1<T> b3) {
  528.         return new FieldUnivariateDerivative1<>(b1.f0.linearCombination(a1, b1.f0,
  529.                                                                         a2, b2.f0,
  530.                                                                         a3, b3.f0),
  531.                                                 b1.f0.linearCombination(a1, b1.f1,
  532.                                                                         a2, b2.f1,
  533.                                                                         a3, b3.f1));
  534.     }

  535.     /** {@inheritDoc} */
  536.     @Override
  537.     public FieldUnivariateDerivative1<T> linearCombination(final double a1, final FieldUnivariateDerivative1<T> b1,
  538.                                                            final double a2, final FieldUnivariateDerivative1<T> b2,
  539.                                                            final double a3, final FieldUnivariateDerivative1<T> b3) {
  540.         return new FieldUnivariateDerivative1<>(b1.f0.linearCombination(a1, b1.f0,
  541.                                                                         a2, b2.f0,
  542.                                                                         a3, b3.f0),
  543.                                                 b1.f0.linearCombination(a1, b1.f1,
  544.                                                                         a2, b2.f1,
  545.                                                                         a3, b3.f1));
  546.     }

  547.     /** {@inheritDoc} */
  548.     @Override
  549.     public FieldUnivariateDerivative1<T> linearCombination(final FieldUnivariateDerivative1<T> a1, final FieldUnivariateDerivative1<T> b1,
  550.                                                            final FieldUnivariateDerivative1<T> a2, final FieldUnivariateDerivative1<T> b2,
  551.                                                            final FieldUnivariateDerivative1<T> a3, final FieldUnivariateDerivative1<T> b3,
  552.                                                            final FieldUnivariateDerivative1<T> a4, final FieldUnivariateDerivative1<T> b4) {
  553.         final Field<T> field = a1.f0.getField();
  554.         final T[] a = MathArrays.buildArray(field, 8);
  555.         final T[] b = MathArrays.buildArray(field, 8);
  556.         a[0] = a1.f0;
  557.         a[1] = a1.f1;
  558.         a[2] = a2.f0;
  559.         a[3] = a2.f1;
  560.         a[4] = a3.f0;
  561.         a[5] = a3.f1;
  562.         a[6] = a4.f0;
  563.         a[7] = a4.f1;
  564.         b[0] = b1.f1;
  565.         b[1] = b1.f0;
  566.         b[2] = b2.f1;
  567.         b[3] = b2.f0;
  568.         b[4] = b3.f1;
  569.         b[5] = b3.f0;
  570.         b[6] = b4.f1;
  571.         b[7] = b4.f0;
  572.         return new FieldUnivariateDerivative1<>(a1.f0.linearCombination(a1.f0, b1.f0,
  573.                                                                         a2.f0, b2.f0,
  574.                                                                         a3.f0, b3.f0,
  575.                                                                         a4.f0, b4.f0),
  576.                                                 a1.f0.linearCombination(a, b));
  577.     }

  578.     /** {@inheritDoc} */
  579.     @Override
  580.     public FieldUnivariateDerivative1<T> linearCombination(final double a1, final FieldUnivariateDerivative1<T> b1,
  581.                                                            final double a2, final FieldUnivariateDerivative1<T> b2,
  582.                                                            final double a3, final FieldUnivariateDerivative1<T> b3,
  583.                                                            final double a4, final FieldUnivariateDerivative1<T> b4) {
  584.         return new FieldUnivariateDerivative1<>(b1.f0.linearCombination(a1, b1.f0,
  585.                                                                         a2, b2.f0,
  586.                                                                         a3, b3.f0,
  587.                                                                         a4, b4.f0),
  588.                                                 b1.f0.linearCombination(a1, b1.f1,
  589.                                                                         a2, b2.f1,
  590.                                                                         a3, b3.f1,
  591.                                                                         a4, b4.f1));
  592.     }

  593.     /** {@inheritDoc} */
  594.     @Override
  595.     public FieldUnivariateDerivative1<T> getPi() {
  596.         final T zero = getValueField().getZero();
  597.         return new FieldUnivariateDerivative1<>(zero.getPi(), zero);
  598.     }

  599.     /** Test for the equality of two univariate derivatives.
  600.      * <p>
  601.      * univariate derivatives are considered equal if they have the same derivatives.
  602.      * </p>
  603.      * @param other Object to test for equality to this
  604.      * @return true if two univariate derivatives are equal
  605.      */
  606.     @Override
  607.     public boolean equals(Object other) {

  608.         if (this == other) {
  609.             return true;
  610.         }

  611.         if (other instanceof FieldUnivariateDerivative1) {
  612.             @SuppressWarnings("unchecked")
  613.             final FieldUnivariateDerivative1<T> rhs = (FieldUnivariateDerivative1<T>) other;
  614.             return f0.equals(rhs.f0) && f1.equals(rhs.f1);
  615.         }

  616.         return false;

  617.     }

  618.     /** Get a hashCode for the univariate derivative.
  619.      * @return a hash code value for this object
  620.      */
  621.     @Override
  622.     public int hashCode() {
  623.         return 453 - 19 * f0.hashCode() + 37 * f1.hashCode();
  624.     }

  625. }