FieldTuple.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.util;

  18. import java.util.Arrays;

  19. import org.hipparchus.CalculusFieldElement;
  20. import org.hipparchus.Field;
  21. import org.hipparchus.exception.MathIllegalArgumentException;

  22. /**
  23.  * This class allows to perform the same computation of all components of a Tuple at once.
  24.  * @param <T> the type of the field elements
  25.  * @since 1.2
  26.  */
  27. public class FieldTuple<T extends CalculusFieldElement<T>> implements CalculusFieldElement<FieldTuple<T>> {

  28.     /** Components of the tuple. */
  29.     private final T[] values;

  30.     /** Field the instance belongs to. */
  31.     private final transient FieldTupleField<T> field;

  32.     /** Creates a new instance from its components.
  33.      * @param x components of the tuple
  34.      */
  35.     @SafeVarargs
  36.     public FieldTuple(final T... x) {
  37.         this(new FieldTupleField<>(x[0].getField(), x.length), x.clone());
  38.     }

  39.     /** Creates a new instance from its components.
  40.      * @param field field the instance belongs to
  41.      * @param x components of the tuple (beware, it is <em>not</em> copied, it is shared with caller)
  42.      */
  43.     private FieldTuple(final FieldTupleField<T> field, final T[] x) { // NOPMD - storing user-supplied array is intentional and documented here
  44.         this.values = x;
  45.         this.field  = field;
  46.     }

  47.     /** {@inheritDoc} */
  48.     @Override
  49.     public FieldTuple<T> newInstance(final double value) {
  50.         return field.getZero().add(value);
  51.     }

  52.     /** Get the dimension of the tuple.
  53.      * @return dimension of the tuple
  54.      */
  55.     public int getDimension() {
  56.         return values.length;
  57.     }

  58.     /** Get one component of the tuple.
  59.      * @param index index of the component, between 0 and {@link #getDimension() getDimension()} - 1
  60.      * @return value of the component
  61.      */
  62.     public T getComponent(final int index) {
  63.         return values[index];
  64.     }

  65.     /** Get all components of the tuple.
  66.      * @return all components
  67.      */
  68.     public T[] getComponents() {
  69.         return values.clone();
  70.     }

  71.     /** {@inheritDoc} */
  72.     @Override
  73.     public Field<FieldTuple<T>> getField() {
  74.         return field;
  75.     }

  76.     /** {@inheritDoc} */
  77.     @Override
  78.     public FieldTuple<T> add(final FieldTuple<T> a) {
  79.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  80.         for (int i = 0; i < values.length; ++i) {
  81.             result.values[i] = values[i].add(a.values[i]);
  82.         }
  83.         return result;
  84.     }

  85.     /** {@inheritDoc} */
  86.     @Override
  87.     public FieldTuple<T> subtract(final FieldTuple<T> a) {
  88.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  89.         for (int i = 0; i < values.length; ++i) {
  90.             result.values[i] = values[i].subtract(a.values[i]);
  91.         }
  92.         return result;
  93.     }

  94.     /** {@inheritDoc} */
  95.     @Override
  96.     public FieldTuple<T> negate() {
  97.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  98.         for (int i = 0; i < values.length; ++i) {
  99.             result.values[i] = values[i].negate();
  100.         }
  101.         return result;
  102.     }

  103.     /** {@inheritDoc} */
  104.     @Override
  105.     public FieldTuple<T> multiply(final FieldTuple<T> a) {
  106.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  107.         for (int i = 0; i < values.length; ++i) {
  108.             result.values[i] = values[i].multiply(a.values[i]);
  109.         }
  110.         return result;
  111.     }

  112.     /** {@inheritDoc} */
  113.     @Override
  114.     public FieldTuple<T> multiply(final int n) {
  115.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  116.         for (int i = 0; i < values.length; ++i) {
  117.             result.values[i] = values[i].multiply(n);
  118.         }
  119.         return result;
  120.     }

  121.     /** {@inheritDoc} */
  122.     @Override
  123.     public FieldTuple<T> divide(final FieldTuple<T> a) {
  124.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  125.         for (int i = 0; i < values.length; ++i) {
  126.             result.values[i] = values[i].divide(a.values[i]);
  127.         }
  128.         return result;
  129.     }

  130.     /** {@inheritDoc} */
  131.     @Override
  132.     public FieldTuple<T> reciprocal() {
  133.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  134.         for (int i = 0; i < values.length; ++i) {
  135.             result.values[i] = values[i].reciprocal();
  136.         }
  137.         return result;
  138.     }

  139.     /** {@inheritDoc} */
  140.     @Override
  141.     public boolean equals(final Object obj) {
  142.         if (obj instanceof FieldTuple<?> ) {
  143.             @SuppressWarnings("unchecked")
  144.             final FieldTuple<T> that = (FieldTuple<T>) obj;
  145.             if (getDimension() == that.getDimension()) {
  146.                 boolean equals = true;
  147.                 for (int i = 0; i < values.length; ++i) {
  148.                     equals &= values[i].equals(that.values[i]);
  149.                 }
  150.                 return equals;
  151.             }
  152.         }
  153.         return false;
  154.     }

  155.     /** {@inheritDoc} */
  156.     @Override
  157.     public int hashCode() {
  158.         return  0x58f61de5 + Arrays.hashCode(values);
  159.     }

  160.     /** {@inheritDoc} */
  161.     @Override
  162.     public double getReal() {
  163.         return values[0].getReal();
  164.     }

  165.     /** {@inheritDoc} */
  166.     @Override
  167.     public FieldTuple<T> getAddendum() {
  168.         final T[] addendum = values.clone();
  169.         addendum[0] = addendum[0].getField().getZero();
  170.         for (int i = 1; i < addendum.length; ++i) {
  171.             addendum[i] = addendum[i].subtract(values[0]);
  172.         }
  173.         return new FieldTuple<>(field, addendum);
  174.     }

  175.     /** {@inheritDoc} */
  176.     @Override
  177.     public FieldTuple<T> add(final double a) {
  178.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  179.         for (int i = 0; i < values.length; ++i) {
  180.             result.values[i] = values[i].add(a);
  181.         }
  182.         return result;
  183.     }

  184.     /** {@inheritDoc} */
  185.     @Override
  186.     public FieldTuple<T> subtract(final double a) {
  187.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  188.         for (int i = 0; i < values.length; ++i) {
  189.             result.values[i] = values[i].subtract(a);
  190.         }
  191.         return result;
  192.     }

  193.     /** {@inheritDoc} */
  194.     @Override
  195.     public FieldTuple<T> multiply(final double a) {
  196.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  197.         for (int i = 0; i < values.length; ++i) {
  198.             result.values[i] = values[i].multiply(a);
  199.         }
  200.         return result;
  201.     }

  202.     /** {@inheritDoc} */
  203.     @Override
  204.     public FieldTuple<T> square() {
  205.         return multiply(this);
  206.     }

  207.     /** {@inheritDoc} */
  208.     @Override
  209.     public FieldTuple<T> divide(final double a) {
  210.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  211.         for (int i = 0; i < values.length; ++i) {
  212.             result.values[i] = values[i].divide(a);
  213.         }
  214.         return result;
  215.     }

  216.     /** {@inheritDoc} */
  217.     @Override
  218.     public FieldTuple<T> remainder(final double a) {
  219.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  220.         for (int i = 0; i < values.length; ++i) {
  221.             result.values[i] = values[i].remainder(a);
  222.         }
  223.         return result;
  224.     }

  225.     /** {@inheritDoc} */
  226.     @Override
  227.     public FieldTuple<T> remainder(final FieldTuple<T> a) {
  228.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  229.         for (int i = 0; i < values.length; ++i) {
  230.             result.values[i] = values[i].remainder(a.values[i]);
  231.         }
  232.         return result;
  233.     }

  234.     /** {@inheritDoc} */
  235.     @Override
  236.     public FieldTuple<T> abs() {
  237.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  238.         for (int i = 0; i < values.length; ++i) {
  239.             result.values[i] = values[i].abs();
  240.         }
  241.         return result;
  242.     }

  243.     /** {@inheritDoc} */
  244.     @Override
  245.     public FieldTuple<T> ceil() {
  246.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  247.         for (int i = 0; i < values.length; ++i) {
  248.             result.values[i] = values[i].ceil();
  249.         }
  250.         return result;
  251.     }

  252.     /** {@inheritDoc} */
  253.     @Override
  254.     public FieldTuple<T> floor() {
  255.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  256.         for (int i = 0; i < values.length; ++i) {
  257.             result.values[i] = values[i].floor();
  258.         }
  259.         return result;
  260.     }

  261.     /** {@inheritDoc} */
  262.     @Override
  263.     public FieldTuple<T> rint() {
  264.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  265.         for (int i = 0; i < values.length; ++i) {
  266.             result.values[i] = values[i].rint();
  267.         }
  268.         return result;
  269.     }

  270.     /** {@inheritDoc} */
  271.     @Override
  272.     public FieldTuple<T> sign() {
  273.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  274.         for (int i = 0; i < values.length; ++i) {
  275.             result.values[i] = values[i].sign();
  276.         }
  277.         return result;
  278.     }

  279.     /** {@inheritDoc} */
  280.     @Override
  281.     public FieldTuple<T> copySign(final FieldTuple<T> sign) {
  282.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  283.         for (int i = 0; i < values.length; ++i) {
  284.             result.values[i] = values[i].copySign(sign.values[i]);
  285.         }
  286.         return result;
  287.     }

  288.     /** {@inheritDoc} */
  289.     @Override
  290.     public FieldTuple<T> copySign(final double sign) {
  291.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  292.         for (int i = 0; i < values.length; ++i) {
  293.             result.values[i] = values[i].copySign(sign);
  294.         }
  295.         return result;
  296.     }

  297.     /** {@inheritDoc} */
  298.     @Override
  299.     public FieldTuple<T> scalb(final int n) {
  300.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  301.         for (int i = 0; i < values.length; ++i) {
  302.             result.values[i] = values[i].scalb(n);
  303.         }
  304.         return result;
  305.     }

  306.     /** {@inheritDoc} */
  307.     @Override
  308.     public FieldTuple<T> ulp() {
  309.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  310.         for (int i = 0; i < values.length; ++i) {
  311.             result.values[i] = values[i].ulp();
  312.         }
  313.         return result;
  314.     }

  315.     /** {@inheritDoc} */
  316.     @Override
  317.     public FieldTuple<T> hypot(final FieldTuple<T> y) {
  318.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  319.         for (int i = 0; i < values.length; ++i) {
  320.             result.values[i] = values[i].hypot(y.values[i]);
  321.         }
  322.         return result;
  323.     }

  324.     /** {@inheritDoc} */
  325.     @Override
  326.     public FieldTuple<T> sqrt() {
  327.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  328.         for (int i = 0; i < values.length; ++i) {
  329.             result.values[i] = values[i].sqrt();
  330.         }
  331.         return result;
  332.     }

  333.     /** {@inheritDoc} */
  334.     @Override
  335.     public FieldTuple<T> cbrt() {
  336.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  337.         for (int i = 0; i < values.length; ++i) {
  338.             result.values[i] = values[i].cbrt();
  339.         }
  340.         return result;
  341.     }

  342.     /** {@inheritDoc} */
  343.     @Override
  344.     public FieldTuple<T> rootN(final int n) {
  345.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  346.         for (int i = 0; i < values.length; ++i) {
  347.             result.values[i] = values[i].rootN(n);
  348.         }
  349.         return result;
  350.     }

  351.     /** {@inheritDoc} */
  352.     @Override
  353.     public FieldTuple<T> pow(final double p) {
  354.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  355.         for (int i = 0; i < values.length; ++i) {
  356.             result.values[i] = values[i].pow(p);
  357.         }
  358.         return result;
  359.     }

  360.     /** {@inheritDoc} */
  361.     @Override
  362.     public FieldTuple<T> pow(final int n) {
  363.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  364.         for (int i = 0; i < values.length; ++i) {
  365.             result.values[i] = values[i].pow(n);
  366.         }
  367.         return result;
  368.     }

  369.     /** {@inheritDoc} */
  370.     @Override
  371.     public FieldTuple<T> pow(final FieldTuple<T> e) {
  372.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  373.         for (int i = 0; i < values.length; ++i) {
  374.             result.values[i] = values[i].pow(e.values[i]);
  375.         }
  376.         return result;
  377.     }

  378.     /** {@inheritDoc} */
  379.     @Override
  380.     public FieldTuple<T> exp() {
  381.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  382.         for (int i = 0; i < values.length; ++i) {
  383.             result.values[i] = values[i].exp();
  384.         }
  385.         return result;
  386.     }

  387.     /** {@inheritDoc} */
  388.     @Override
  389.     public FieldTuple<T> expm1() {
  390.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  391.         for (int i = 0; i < values.length; ++i) {
  392.             result.values[i] = values[i].expm1();
  393.         }
  394.         return result;
  395.     }

  396.     /** {@inheritDoc} */
  397.     @Override
  398.     public FieldTuple<T> log() {
  399.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  400.         for (int i = 0; i < values.length; ++i) {
  401.             result.values[i] = values[i].log();
  402.         }
  403.         return result;
  404.     }

  405.     /** {@inheritDoc} */
  406.     @Override
  407.     public FieldTuple<T> log1p() {
  408.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  409.         for (int i = 0; i < values.length; ++i) {
  410.             result.values[i] = values[i].log1p();
  411.         }
  412.         return result;
  413.     }

  414.     /** {@inheritDoc} */
  415.     @Override
  416.     public FieldTuple<T> log10() {
  417.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  418.         for (int i = 0; i < values.length; ++i) {
  419.             result.values[i] = values[i].log10();
  420.         }
  421.         return result;
  422.     }

  423.     /** {@inheritDoc} */
  424.     @Override
  425.     public FieldTuple<T> cos() {
  426.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  427.         for (int i = 0; i < values.length; ++i) {
  428.             result.values[i] = values[i].cos();
  429.         }
  430.         return result;
  431.     }

  432.     /** {@inheritDoc} */
  433.     @Override
  434.     public FieldTuple<T> sin() {
  435.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  436.         for (int i = 0; i < values.length; ++i) {
  437.             result.values[i] = values[i].sin();
  438.         }
  439.         return result;
  440.     }

  441.     /** {@inheritDoc} */
  442.     @Override
  443.     public FieldSinCos<FieldTuple<T>> sinCos() {
  444.         final FieldTuple<T> sin = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  445.         final FieldTuple<T> cos = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  446.         for (int i = 0; i < values.length; ++i) {
  447.             final FieldSinCos<T> sc = FastMath.sinCos(values[i]);
  448.             sin.values[i] = sc.sin();
  449.             cos.values[i] = sc.cos();
  450.         }
  451.         return new FieldSinCos<>(sin, cos);
  452.     }

  453.     /** {@inheritDoc} */
  454.     @Override
  455.     public FieldTuple<T> tan() {
  456.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  457.         for (int i = 0; i < values.length; ++i) {
  458.             result.values[i] = values[i].tan();
  459.         }
  460.         return result;
  461.     }

  462.     /** {@inheritDoc} */
  463.     @Override
  464.     public FieldTuple<T> acos() {
  465.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  466.         for (int i = 0; i < values.length; ++i) {
  467.             result.values[i] = values[i].acos();
  468.         }
  469.         return result;
  470.     }

  471.     /** {@inheritDoc} */
  472.     @Override
  473.     public FieldTuple<T> asin() {
  474.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  475.         for (int i = 0; i < values.length; ++i) {
  476.             result.values[i] = values[i].asin();
  477.         }
  478.         return result;
  479.     }

  480.     /** {@inheritDoc} */
  481.     @Override
  482.     public FieldTuple<T> atan() {
  483.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  484.         for (int i = 0; i < values.length; ++i) {
  485.             result.values[i] = values[i].atan();
  486.         }
  487.         return result;
  488.     }

  489.     /** {@inheritDoc} */
  490.     @Override
  491.     public FieldTuple<T> atan2(final FieldTuple<T> x) {
  492.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  493.         for (int i = 0; i < values.length; ++i) {
  494.             result.values[i] = values[i].atan2(x.values[i]);
  495.         }
  496.         return result;
  497.     }

  498.     /** {@inheritDoc} */
  499.     @Override
  500.     public FieldTuple<T> cosh() {
  501.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  502.         for (int i = 0; i < values.length; ++i) {
  503.             result.values[i] = values[i].cosh();
  504.         }
  505.         return result;
  506.     }

  507.     /** {@inheritDoc} */
  508.     @Override
  509.     public FieldTuple<T> sinh() {
  510.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  511.         for (int i = 0; i < values.length; ++i) {
  512.             result.values[i] = values[i].sinh();
  513.         }
  514.         return result;
  515.     }

  516.     /** {@inheritDoc} */
  517.     @Override
  518.     public FieldSinhCosh<FieldTuple<T>> sinhCosh() {
  519.         final FieldTuple<T> sinh = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  520.         final FieldTuple<T> cosh = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  521.         for (int i = 0; i < values.length; ++i) {
  522.             final FieldSinhCosh<T> sc = FastMath.sinhCosh(values[i]);
  523.             sinh.values[i] = sc.sinh();
  524.             cosh.values[i] = sc.cosh();
  525.         }
  526.         return new FieldSinhCosh<>(sinh, cosh);
  527.     }

  528.     /** {@inheritDoc} */
  529.     @Override
  530.     public FieldTuple<T> tanh() {
  531.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  532.         for (int i = 0; i < values.length; ++i) {
  533.             result.values[i] = values[i].tanh();
  534.         }
  535.         return result;
  536.     }

  537.     /** {@inheritDoc} */
  538.     @Override
  539.     public FieldTuple<T> acosh() {
  540.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  541.         for (int i = 0; i < values.length; ++i) {
  542.             result.values[i] = values[i].acosh();
  543.         }
  544.         return result;
  545.     }

  546.     /** {@inheritDoc} */
  547.     @Override
  548.     public FieldTuple<T> asinh() {
  549.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  550.         for (int i = 0; i < values.length; ++i) {
  551.             result.values[i] = values[i].asinh();
  552.         }
  553.         return result;
  554.     }

  555.     /** {@inheritDoc} */
  556.     @Override
  557.     public FieldTuple<T> atanh() {
  558.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  559.         for (int i = 0; i < values.length; ++i) {
  560.             result.values[i] = values[i].atanh();
  561.         }
  562.         return result;
  563.     }

  564.     /** {@inheritDoc} */
  565.     @Override
  566.     public FieldTuple<T> toDegrees() {
  567.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  568.         for (int i = 0; i < values.length; ++i) {
  569.             result.values[i] = values[i].toDegrees();
  570.         }
  571.         return result;
  572.     }

  573.     /** {@inheritDoc} */
  574.     @Override
  575.     public FieldTuple<T> toRadians() {
  576.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  577.         for (int i = 0; i < values.length; ++i) {
  578.             result.values[i] = values[i].toRadians();
  579.         }
  580.         return result;
  581.     }

  582.     /** {@inheritDoc} */
  583.     @Override
  584.     public FieldTuple<T> linearCombination(final FieldTuple<T>[] a, final FieldTuple<T>[] b)
  585.         throws MathIllegalArgumentException {
  586.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  587.         MathUtils.checkDimension(a.length, b.length);
  588.         final T[] aT = MathArrays.buildArray(values[0].getField(), a.length);
  589.         final T[] bT = MathArrays.buildArray(values[0].getField(), b.length);
  590.         for (int i = 0; i < values.length; ++i) {
  591.             for (int j = 0; j < a.length; ++j) {
  592.                 aT[j] = a[j].values[i];
  593.                 bT[j] = b[j].values[i];
  594.             }
  595.             result.values[i] = aT[0].linearCombination(aT, bT);
  596.         }
  597.         return result;
  598.     }

  599.     /** {@inheritDoc} */
  600.     @Override
  601.     public FieldTuple<T> linearCombination(final double[] a, final FieldTuple<T>[] b)
  602.         throws MathIllegalArgumentException {
  603.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  604.         MathUtils.checkDimension(a.length, b.length);
  605.         final T[] bT = MathArrays.buildArray(values[0].getField(), b.length);
  606.         for (int i = 0; i < values.length; ++i) {
  607.             for (int j = 0; j < a.length; ++j) {
  608.                 bT[j] = b[j].values[i];
  609.             }
  610.             result.values[i] = bT[0].linearCombination(a, bT);
  611.         }
  612.         return result;
  613.     }

  614.     /** {@inheritDoc} */
  615.     @Override
  616.     public FieldTuple<T> linearCombination(final FieldTuple<T> a1, final FieldTuple<T> b1,
  617.                                            final FieldTuple<T> a2, final FieldTuple<T> b2) {
  618.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  619.         for (int i = 0; i < values.length; ++i) {
  620.             result.values[i] = a1.values[0].linearCombination(a1.values[i], b1.values[i],
  621.                                                               a2.values[i], b2.values[i]);
  622.         }
  623.         return result;
  624.     }

  625.     /** {@inheritDoc} */
  626.     @Override
  627.     public FieldTuple<T> linearCombination(final double a1, final FieldTuple<T> b1,
  628.                                            final double a2, final FieldTuple<T> b2) {
  629.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  630.         for (int i = 0; i < values.length; ++i) {
  631.             result.values[i] = b1.values[0].linearCombination(a1, b1.values[i],
  632.                                                               a2, b2.values[i]);
  633.         }
  634.         return result;
  635.     }

  636.     /** {@inheritDoc} */
  637.     @Override
  638.     public FieldTuple<T> linearCombination(final FieldTuple<T> a1, final FieldTuple<T> b1,
  639.                                            final FieldTuple<T> a2, final FieldTuple<T> b2,
  640.                                            final FieldTuple<T> a3, final FieldTuple<T> b3) {
  641.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  642.         for (int i = 0; i < values.length; ++i) {
  643.             result.values[i] = a1.values[0].linearCombination(a1.values[i], b1.values[i],
  644.                                                               a2.values[i], b2.values[i],
  645.                                                               a3.values[i], b3.values[i]);
  646.         }
  647.         return result;
  648.     }

  649.     /** {@inheritDoc} */
  650.     @Override
  651.     public FieldTuple<T> linearCombination(final double a1, final FieldTuple<T> b1,
  652.                                            final double a2, final FieldTuple<T> b2,
  653.                                            final double a3, final FieldTuple<T> b3) {
  654.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  655.         for (int i = 0; i < values.length; ++i) {
  656.             result.values[i] = b1.values[0].linearCombination(a1, b1.values[i],
  657.                                                               a2, b2.values[i],
  658.                                                               a3, b3.values[i]);
  659.         }
  660.         return result;
  661.     }

  662.     /** {@inheritDoc} */
  663.     @Override
  664.     public FieldTuple<T> linearCombination(final FieldTuple<T> a1, final FieldTuple<T> b1,
  665.                                            final FieldTuple<T> a2, final FieldTuple<T> b2,
  666.                                            final FieldTuple<T> a3, final FieldTuple<T> b3,
  667.                                            final FieldTuple<T> a4, final FieldTuple<T> b4) {
  668.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  669.         for (int i = 0; i < values.length; ++i) {
  670.             result.values[i] = a1.values[0].linearCombination(a1.values[i], b1.values[i],
  671.                                                               a2.values[i], b2.values[i],
  672.                                                               a3.values[i], b3.values[i],
  673.                                                               a4.values[i], b4.values[i]);
  674.         }
  675.         return result;
  676.     }

  677.     /** {@inheritDoc} */
  678.     @Override
  679.     public FieldTuple<T> linearCombination(final double a1, final FieldTuple<T> b1,
  680.                                            final double a2, final FieldTuple<T> b2,
  681.                                            final double a3, final FieldTuple<T> b3,
  682.                                            final double a4, final FieldTuple<T> b4) {
  683.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  684.         for (int i = 0; i < values.length; ++i) {
  685.             result.values[i] = b1.values[0].linearCombination(a1, b1.values[i],
  686.                                                               a2, b2.values[i],
  687.                                                               a3, b3.values[i],
  688.                                                               a4, b4.values[i]);
  689.         }
  690.         return result;
  691.     }

  692.     /** {@inheritDoc} */
  693.     @Override
  694.     public FieldTuple<T> getPi() {
  695.         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
  696.         Arrays.fill(result.values, values[0].getPi());
  697.         return result;
  698.     }

  699.     /** Field for {link FieldTuple} instances.
  700.      * @param <T> the type of the field elements
  701.      */
  702.     private static class FieldTupleField<T extends CalculusFieldElement<T>> implements Field<FieldTuple<T>> {

  703.         /** Constant function evaluating to 0.0. */
  704.         private final FieldTuple<T> zero;

  705.         /** Constant function evaluating to 1.0. */
  706.         private final FieldTuple<T> one;

  707.         /** Simple constructor.
  708.          * @param field field to which the elements belong
  709.          * @param dimension dimension of the tuple
  710.          */
  711.         FieldTupleField(final Field<T> field, final int dimension) {
  712.             final T[] zeroData = MathArrays.buildArray(field, dimension);
  713.             Arrays.fill(zeroData, field.getZero());
  714.             final T[] oneData  = MathArrays.buildArray(field, dimension);
  715.             Arrays.fill(oneData, field.getOne());
  716.             this.zero = new FieldTuple<>(this, zeroData);
  717.             this.one  = new FieldTuple<>(this, oneData);
  718.         }

  719.         /** {@inheritDoc} */
  720.         @Override
  721.         public FieldTuple<T> getZero() {
  722.             return zero;
  723.         }

  724.         /** {@inheritDoc} */
  725.         @Override
  726.         public FieldTuple<T> getOne() {
  727.             return one;
  728.         }

  729.         /** {@inheritDoc} */
  730.         @SuppressWarnings("unchecked")
  731.         @Override
  732.         public Class<FieldTuple<T>> getRuntimeClass() {
  733.             return (Class<FieldTuple<T>>) zero.getClass();
  734.         }

  735.         /** {@inheritDoc} */
  736.         @Override
  737.         public boolean equals(final Object other) {
  738.             if (other instanceof FieldTupleField) {
  739.                 @SuppressWarnings("unchecked")
  740.                 final FieldTupleField<T> that = (FieldTupleField<T>) other;
  741.                 return zero.getDimension() == that.zero.getDimension();
  742.             } else {
  743.                 return false;
  744.             }
  745.         }

  746.         /** {@inheritDoc} */
  747.         @Override
  748.         public int hashCode() {
  749.             return 0xb4a533e1 ^ zero.getDimension();
  750.         }

  751.     }

  752. }