gt:         compiler.multiply(data, 0, a.data, 0, result.data, 0);
context: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.commons.math3.analysis.differentiation;
  
  import java.io.Serializable;
  
  import org.apache.commons.math3.Field;
  import org.apache.commons.math3.FieldElement;
  import org.apache.commons.math3.RealFieldElement;
  import org.apache.commons.math3.exception.DimensionMismatchException;
  import org.apache.commons.math3.exception.MathArithmeticException;
  import org.apache.commons.math3.exception.NumberIsTooLargeException;
  import org.apache.commons.math3.util.FastMath;
  import org.apache.commons.math3.util.MathArrays;
  import org.apache.commons.math3.util.MathUtils;
  
  /** Class representing both the value and the differentials of a function.
   * <p>This class is the workhorse of the differentiation package.</p>
   * <p>This class is an implementation of the extension to Rall's
   * numbers described in Dan Kalman's paper <a
   * href="http://www1.american.edu/cas/mathstat/People/kalman/pdffiles/mmgautodiff.pdf">Doubly
   * Recursive Multivariate Automatic Differentiation</a>, Mathematics Magazine, vol. 75,
   * no. 3, June 2002. Rall's numbers are an extension to the real numbers used
   * throughout mathematical expressions; they hold the derivative together with the
   * value of a function. Dan Kalman's derivative structures hold all partial derivatives
   * up to any specified order, with respect to any number of free parameters. Rall's
   * numbers therefore can be seen as derivative structures for order one derivative and
   * one free parameter, and real numbers can be seen as derivative structures with zero
   * order derivative and no free parameters.</p>
   * <p>{@link DerivativeStructure} instances can be used directly thanks to
   * the arithmetic operators to the mathematical functions provided as
   * methods by this class (+, -, *, /, %, sin, cos ...).</p>
   * <p>Implementing complex expressions by hand using these classes is
   * a tedious and error-prone task but has the advantage of having no limitation
   * on the derivation order despite no requiring users to compute the derivatives by
   * themselves. Implementing complex expression can also be done by developing computation
   * code using standard primitive double values and to use {@link
   * UnivariateFunctionDifferentiator differentiators} to create the {@link
   * DerivativeStructure}-based instances. This method is simpler but may be limited in
   * the accuracy and derivation orders and may be computationally intensive (this is
   * typically the case for {@link FiniteDifferencesDifferentiator finite differences
   * differentiator}.</p>
   * <p>Instances of this class are guaranteed to be immutable.</p>
   * @see DSCompiler
   * @since 3.1
   */
  public class DerivativeStructure implements RealFieldElement<DerivativeStructure>, Serializable {
  
      /** Serializable UID. */
      private static final long serialVersionUID = 20120730L;
  
      /** Compiler for the current dimensions. */
      private transient DSCompiler compiler;
  
      /** Combined array holding all values. */
      private final double[] data;
  
      /** Build an instance with all values and derivatives set to 0.
       * @param compiler compiler to use for computation
       */
      private DerivativeStructure(final DSCompiler compiler) {
          this.compiler = compiler;
          this.data     = new double[compiler.getSize()];
      }
  
      /** Build an instance with all values and derivatives set to 0.
       * @param parameters number of free parameters
       * @param order derivation order
       * @throws NumberIsTooLargeException if order is too large
       */
      public DerivativeStructure(final int parameters, final int order)
          throws NumberIsTooLargeException {
          this(DSCompiler.getCompiler(parameters, order));
      }
  
      /** Build an instance representing a constant value.
       * @param parameters number of free parameters
       * @param order derivation order
       * @param value value of the constant
       * @throws NumberIsTooLargeException if order is too large
       * @see #DerivativeStructure(int, int, int, double)
       */
      public DerivativeStructure(final int parameters, final int order, final double value)
          throws NumberIsTooLargeException {
          this(parameters, order);
          this.data[0] = value;
      }
  
      /** Build an instance representing a variable.
       * <p>Instances built using this constructor are considered
       * to be the free variables with respect to which differentials
       * are computed. As such, their differential with respect to
       * themselves is +1.</p>
       * @param parameters number of free parameters
       * @param order derivation order
       * @param index index of the variable (from 0 to {@code parameters - 1})
       * @param value value of the variable
       * @exception NumberIsTooLargeException if {@code index >= parameters}.
       * @see #DerivativeStructure(int, int, double)
       */
      public DerivativeStructure(final int parameters, final int order,
                                 final int index, final double value)
          throws NumberIsTooLargeException {
          this(parameters, order, value);
  
          if (index >= parameters) {
              throw new NumberIsTooLargeException(index, parameters, false);
          }
  
          if (order > 0) {
              // the derivative of the variable with respect to itself is 1.
              data[DSCompiler.getCompiler(index, order).getSize()] = 1.0;
          }
  
      }
  
      /** Linear combination constructor.
       * The derivative structure built will be a1 * ds1 + a2 * ds2
       * @param a1 first scale factor
       * @param ds1 first base (unscaled) derivative structure
       * @param a2 second scale factor
       * @param ds2 second base (unscaled) derivative structure
       * @exception DimensionMismatchException if number of free parameters or orders are inconsistent
       */
      public DerivativeStructure(final double a1, final DerivativeStructure ds1,
                                 final double a2, final DerivativeStructure ds2)
          throws DimensionMismatchException {
          this(ds1.compiler);
          compiler.checkCompatibility(ds2.compiler);
          compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, data, 0);
      }
  
      /** Linear combination constructor.
       * The derivative structure built will be a1 * ds1 + a2 * ds2 + a3 * ds3
       * @param a1 first scale factor
       * @param ds1 first base (unscaled) derivative structure
       * @param a2 second scale factor
       * @param ds2 second base (unscaled) derivative structure
       * @param a3 third scale factor
       * @param ds3 third base (unscaled) derivative structure
       * @exception DimensionMismatchException if number of free parameters or orders are inconsistent
       */
      public DerivativeStructure(final double a1, final DerivativeStructure ds1,
                                 final double a2, final DerivativeStructure ds2,
                                 final double a3, final DerivativeStructure ds3)
          throws DimensionMismatchException {
          this(ds1.compiler);
          compiler.checkCompatibility(ds2.compiler);
          compiler.checkCompatibility(ds3.compiler);
          compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, a3, ds3.data, 0, data, 0);
      }
  
      /** Linear combination constructor.
       * The derivative structure built will be a1 * ds1 + a2 * ds2 + a3 * ds3 + a4 * ds4
       * @param a1 first scale factor
       * @param ds1 first base (unscaled) derivative structure
       * @param a2 second scale factor
       * @param ds2 second base (unscaled) derivative structure
       * @param a3 third scale factor
       * @param ds3 third base (unscaled) derivative structure
       * @param a4 fourth scale factor
       * @param ds4 fourth base (unscaled) derivative structure
       * @exception DimensionMismatchException if number of free parameters or orders are inconsistent
       */
      public DerivativeStructure(final double a1, final DerivativeStructure ds1,
                                 final double a2, final DerivativeStructure ds2,
                                 final double a3, final DerivativeStructure ds3,
                                 final double a4, final DerivativeStructure ds4)
          throws DimensionMismatchException {
          this(ds1.compiler);
          compiler.checkCompatibility(ds2.compiler);
          compiler.checkCompatibility(ds3.compiler);
          compiler.checkCompatibility(ds4.compiler);
          compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0,
                                     a3, ds3.data, 0, a4, ds4.data, 0,
                                     data, 0);
      }
  
      /** Build an instance from all its derivatives.
       * @param parameters number of free parameters
       * @param order derivation order
       * @param derivatives derivatives sorted according to
       * {@link DSCompiler#getPartialDerivativeIndex(int...)}
       * @exception DimensionMismatchException if derivatives array does not match the
       * {@link DSCompiler#getSize() size} expected by the compiler
       * @throws NumberIsTooLargeException if order is too large
       * @see #getAllDerivatives()
       */
      public DerivativeStructure(final int parameters, final int order, final double ... derivatives)
          throws DimensionMismatchException, NumberIsTooLargeException {
          this(parameters, order);
          if (derivatives.length != data.length) {
              throw new DimensionMismatchException(derivatives.length, data.length);
          }
          System.arraycopy(derivatives, 0, data, 0, data.length);
      }
  
      /** Copy constructor.
       * @param ds instance to copy
       */
      private DerivativeStructure(final DerivativeStructure ds) {
          this.compiler = ds.compiler;
          this.data     = ds.data.clone();
      }
  
      /** Get the number of free parameters.
       * @return number of free parameters
       */
      public int getFreeParameters() {
          return compiler.getFreeParameters();
      }
  
      /** Get the derivation order.
       * @return derivation order
       */
      public int getOrder() {
          return compiler.getOrder();
      }
  
      /** Create a constant compatible with instance order and number of parameters.
       * <p>
       * This method is a convenience factory method, it simply calls
       * {@code new DerivativeStructure(getFreeParameters(), getOrder(), c)}
       * </p>
       * @param c value of the constant
       * @return a constant compatible with instance order and number of parameters
       * @see #DerivativeStructure(int, int, double)
       * @since 3.3
       */
      public DerivativeStructure createConstant(final double c) {
          return new DerivativeStructure(getFreeParameters(), getOrder(), c);
      }
  
      /** {@inheritDoc}
       * @since 3.2
       */
      public double getReal() {
          return data[0];
      }
  
      /** Get the value part of the derivative structure.
       * @return value part of the derivative structure
       * @see #getPartialDerivative(int...)
       */
      public double getValue() {
          return data[0];
      }
  
      /** Get a partial derivative.
       * @param orders derivation orders with respect to each variable (if all orders are 0,
       * the value is returned)
       * @return partial derivative
       * @see #getValue()
       * @exception DimensionMismatchException if the numbers of variables does not
       * match the instance
       * @exception NumberIsTooLargeException if sum of derivation orders is larger
       * than the instance limits
       */
      public double getPartialDerivative(final int ... orders)
          throws DimensionMismatchException, NumberIsTooLargeException {
          return data[compiler.getPartialDerivativeIndex(orders)];
      }
  
      /** Get all partial derivatives.
       * @return a fresh copy of partial derivatives, in an array sorted according to
       * {@link DSCompiler#getPartialDerivativeIndex(int...)}
       */
      public double[] getAllDerivatives() {
          return data.clone();
      }
  
      /** {@inheritDoc}
       * @since 3.2
       */
      public DerivativeStructure add(final double a) {
          final DerivativeStructure ds = new DerivativeStructure(this);
          ds.data[0] += a;
          return ds;
      }
  
      /** {@inheritDoc}
       * @exception DimensionMismatchException if number of free parameters
       * or orders do not match
       */
      public DerivativeStructure add(final DerivativeStructure a)
          throws DimensionMismatchException {
          compiler.checkCompatibility(a.compiler);
          final DerivativeStructure ds = new DerivativeStructure(this);
          compiler.add(data, 0, a.data, 0, ds.data, 0);
          return ds;
      }
  
      /** {@inheritDoc}
       * @since 3.2
       */
      public DerivativeStructure subtract(final double a) {
          return add(-a);
      }
  
      /** {@inheritDoc}
       * @exception DimensionMismatchException if number of free parameters
       * or orders do not match
       */
      public DerivativeStructure subtract(final DerivativeStructure a)
          throws DimensionMismatchException {
          compiler.checkCompatibility(a.compiler);
          final DerivativeStructure ds = new DerivativeStructure(this);
          compiler.subtract(data, 0, a.data, 0, ds.data, 0);
          return ds;
      }
  
      /** {@inheritDoc} */
      public DerivativeStructure multiply(final int n) {
          return multiply((double) n);
      }
  
      /** {@inheritDoc}
       * @since 3.2
       */
      public DerivativeStructure multiply(final double a) {
          final DerivativeStructure ds = new DerivativeStructure(this);
          for (int i = 0; i < ds.data.length; ++i) {
              ds.data[i] *= a;
          }
          return ds;
      }
  
      /** {@inheritDoc}
       * @exception DimensionMismatchException if number of free parameters
       * or orders do not match
       */
      public DerivativeStructure multiply(final DerivativeStructure a)
          throws DimensionMismatchException {
          compiler.checkCompatibility(a.compiler);
          final DerivativeStructure result = new DerivativeStructure(compiler);
  