Tuple.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.  * @since 1.2
  25.  */
  26. public class Tuple implements CalculusFieldElement<Tuple> {

  27.     /** Components of the tuple. */
  28.     private final double[] values;

  29.     /** Field the instance belongs to. */
  30.     private final transient TupleField field;

  31.     /** Creates a new instance from its components.
  32.      * @param x components of the tuple
  33.      */
  34.     public Tuple(final double... x) {
  35.         this(new TupleField(x.length), x.clone());
  36.     }

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

  45.     /** {@inheritDoc} */
  46.     @Override
  47.     public Tuple newInstance(final double value) {
  48.         final Tuple t = new Tuple(field, new double[values.length]);
  49.         Arrays.fill(t.values, value);
  50.         return t;
  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 double getComponent(final int index) {
  63.         return values[index];
  64.     }

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

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

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

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

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

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

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

  121.     /** {@inheritDoc} */
  122.     @Override
  123.     public Tuple square() {
  124.         return multiply(this);
  125.     }

  126.     /** {@inheritDoc} */
  127.     @Override
  128.     public Tuple divide(final Tuple a) {
  129.         final Tuple result = new Tuple(field, new double[values.length]);
  130.         for (int i = 0; i < values.length; ++i) {
  131.             result.values[i] = values[i] / a.values[i];
  132.         }
  133.         return result;
  134.     }

  135.     /** {@inheritDoc} */
  136.     @Override
  137.     public Tuple reciprocal() {
  138.         final Tuple result = new Tuple(field, new double[values.length]);
  139.         for (int i = 0; i < values.length; ++i) {
  140.             result.values[i] = 1.0 / values[i];
  141.         }
  142.         return result;
  143.     }

  144.     /** {@inheritDoc} */
  145.     @Override
  146.     public boolean equals(final Object obj) {
  147.         if (obj instanceof Tuple) {
  148.             final Tuple that = (Tuple) obj;
  149.             if (getDimension() == that.getDimension()) {
  150.                 boolean equals = true;
  151.                 for (int i = 0; i < values.length; ++i) {
  152.                     equals &= Double.doubleToRawLongBits(values[i]) == Double.doubleToRawLongBits(that.values[i]);
  153.                 }
  154.                 return equals;
  155.             }
  156.         }
  157.         return false;
  158.     }

  159.     /** {@inheritDoc} */
  160.     @Override
  161.     public int hashCode() {
  162.         return  0x34b1a444 + Arrays.hashCode(values);
  163.     }

  164.     /** {@inheritDoc} */
  165.     @Override
  166.     public double getReal() {
  167.         return values[0];
  168.     }

  169.     /** {@inheritDoc} */
  170.     @Override
  171.     public Tuple getAddendum() {
  172.         final double[] addendum = values.clone();
  173.         addendum[0] = 0;
  174.         for (int i = 1; i < addendum.length; ++i) {
  175.             addendum[i] -= values[0];
  176.         }
  177.         return new Tuple(field, addendum);
  178.     }

  179.     /** {@inheritDoc} */
  180.     @Override
  181.     public Tuple add(final double a) {
  182.         final Tuple result = new Tuple(field, new double[values.length]);
  183.         for (int i = 0; i < values.length; ++i) {
  184.             result.values[i] = values[i] + a;
  185.         }
  186.         return result;
  187.     }

  188.     /** {@inheritDoc} */
  189.     @Override
  190.     public Tuple subtract(final double a) {
  191.         final Tuple result = new Tuple(field, new double[values.length]);
  192.         for (int i = 0; i < values.length; ++i) {
  193.             result.values[i] = values[i] - a;
  194.         }
  195.         return result;
  196.     }

  197.     /** {@inheritDoc} */
  198.     @Override
  199.     public Tuple multiply(final double a) {
  200.         final Tuple result = new Tuple(field, new double[values.length]);
  201.         for (int i = 0; i < values.length; ++i) {
  202.             result.values[i] = values[i] * a;
  203.         }
  204.         return result;
  205.     }

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

  215.     /** {@inheritDoc} */
  216.     @Override
  217.     public Tuple remainder(final double a) {
  218.         final Tuple result = new Tuple(field, new double[values.length]);
  219.         for (int i = 0; i < values.length; ++i) {
  220.             result.values[i] = FastMath.IEEEremainder(values[i], a);
  221.         }
  222.         return result;
  223.     }

  224.     /** {@inheritDoc} */
  225.     @Override
  226.     public Tuple remainder(final Tuple a) {
  227.         final Tuple result = new Tuple(field, new double[values.length]);
  228.         for (int i = 0; i < values.length; ++i) {
  229.             result.values[i] = FastMath.IEEEremainder(values[i], a.values[i]);
  230.         }
  231.         return result;
  232.     }

  233.     /** {@inheritDoc} */
  234.     @Override
  235.     public Tuple abs() {
  236.         final Tuple result = new Tuple(field, new double[values.length]);
  237.         for (int i = 0; i < values.length; ++i) {
  238.             result.values[i] = FastMath.abs(values[i]);
  239.         }
  240.         return result;
  241.     }

  242.     /** {@inheritDoc} */
  243.     @Override
  244.     public Tuple ceil() {
  245.         final Tuple result = new Tuple(field, new double[values.length]);
  246.         for (int i = 0; i < values.length; ++i) {
  247.             result.values[i] = FastMath.ceil(values[i]);
  248.         }
  249.         return result;
  250.     }

  251.     /** {@inheritDoc} */
  252.     @Override
  253.     public Tuple floor() {
  254.         final Tuple result = new Tuple(field, new double[values.length]);
  255.         for (int i = 0; i < values.length; ++i) {
  256.             result.values[i] = FastMath.floor(values[i]);
  257.         }
  258.         return result;
  259.     }

  260.     /** {@inheritDoc} */
  261.     @Override
  262.     public Tuple rint() {
  263.         final Tuple result = new Tuple(field, new double[values.length]);
  264.         for (int i = 0; i < values.length; ++i) {
  265.             result.values[i] = FastMath.rint(values[i]);
  266.         }
  267.         return result;
  268.     }

  269.     /** {@inheritDoc} */
  270.     @Override
  271.     public Tuple sign() {
  272.         final Tuple result = new Tuple(field, new double[values.length]);
  273.         for (int i = 0; i < values.length; ++i) {
  274.             result.values[i] = FastMath.signum(values[i]);
  275.         }
  276.         return result;
  277.     }

  278.     /** {@inheritDoc} */
  279.     @Override
  280.     public Tuple copySign(final Tuple sign) {
  281.         final Tuple result = new Tuple(field, new double[values.length]);
  282.         for (int i = 0; i < values.length; ++i) {
  283.             result.values[i] = FastMath.copySign(values[i], sign.values[i]);
  284.         }
  285.         return result;
  286.     }

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

  296.     /** {@inheritDoc} */
  297.     @Override
  298.     public Tuple scalb(final int n) {
  299.         final Tuple result = new Tuple(field, new double[values.length]);
  300.         for (int i = 0; i < values.length; ++i) {
  301.             result.values[i] = FastMath.scalb(values[i], n);
  302.         }
  303.         return result;
  304.     }

  305.     /** {@inheritDoc} */
  306.     @Override
  307.     public Tuple ulp() {
  308.         final Tuple result = new Tuple(field, new double[values.length]);
  309.         for (int i = 0; i < values.length; ++i) {
  310.             result.values[i] = FastMath.ulp(values[i]);
  311.         }
  312.         return result;
  313.     }

  314.     /** {@inheritDoc} */
  315.     @Override
  316.     public Tuple hypot(final Tuple y) {
  317.         final Tuple result = new Tuple(field, new double[values.length]);
  318.         for (int i = 0; i < values.length; ++i) {
  319.             result.values[i] = FastMath.hypot(values[i], y.values[i]);
  320.         }
  321.         return result;
  322.     }

  323.     /** {@inheritDoc} */
  324.     @Override
  325.     public Tuple sqrt() {
  326.         final Tuple result = new Tuple(field, new double[values.length]);
  327.         for (int i = 0; i < values.length; ++i) {
  328.             result.values[i] = FastMath.sqrt(values[i]);
  329.         }
  330.         return result;
  331.     }

  332.     /** {@inheritDoc} */
  333.     @Override
  334.     public Tuple cbrt() {
  335.         final Tuple result = new Tuple(field, new double[values.length]);
  336.         for (int i = 0; i < values.length; ++i) {
  337.             result.values[i] = FastMath.cbrt(values[i]);
  338.         }
  339.         return result;
  340.     }

  341.     /** {@inheritDoc} */
  342.     @Override
  343.     public Tuple rootN(final int n) {
  344.         final Tuple result = new Tuple(field, new double[values.length]);
  345.         for (int i = 0; i < values.length; ++i) {
  346.             if (values[i] < 0) {
  347.                 result.values[i] = -FastMath.pow(-values[i], 1.0 / n);
  348.             } else {
  349.                 result.values[i] = FastMath.pow(values[i], 1.0 / n);
  350.             }
  351.         }
  352.         return result;
  353.     }

  354.     /** {@inheritDoc} */
  355.     @Override
  356.     public Tuple pow(final double p) {
  357.         final Tuple result = new Tuple(field, new double[values.length]);
  358.         for (int i = 0; i < values.length; ++i) {
  359.             result.values[i] = FastMath.pow(values[i], p);
  360.         }
  361.         return result;
  362.     }

  363.     /** {@inheritDoc} */
  364.     @Override
  365.     public Tuple pow(final int n) {
  366.         final Tuple result = new Tuple(field, new double[values.length]);
  367.         for (int i = 0; i < values.length; ++i) {
  368.             result.values[i] = FastMath.pow(values[i], n);
  369.         }
  370.         return result;
  371.     }

  372.     /** {@inheritDoc} */
  373.     @Override
  374.     public Tuple pow(final Tuple e) {
  375.         final Tuple result = new Tuple(field, new double[values.length]);
  376.         for (int i = 0; i < values.length; ++i) {
  377.             result.values[i] = FastMath.pow(values[i], e.values[i]);
  378.         }
  379.         return result;
  380.     }

  381.     /** {@inheritDoc} */
  382.     @Override
  383.     public Tuple exp() {
  384.         final Tuple result = new Tuple(field, new double[values.length]);
  385.         for (int i = 0; i < values.length; ++i) {
  386.             result.values[i] = FastMath.exp(values[i]);
  387.         }
  388.         return result;
  389.     }

  390.     /** {@inheritDoc} */
  391.     @Override
  392.     public Tuple expm1() {
  393.         final Tuple result = new Tuple(field, new double[values.length]);
  394.         for (int i = 0; i < values.length; ++i) {
  395.             result.values[i] = FastMath.expm1(values[i]);
  396.         }
  397.         return result;
  398.     }

  399.     /** {@inheritDoc} */
  400.     @Override
  401.     public Tuple log() {
  402.         final Tuple result = new Tuple(field, new double[values.length]);
  403.         for (int i = 0; i < values.length; ++i) {
  404.             result.values[i] = FastMath.log(values[i]);
  405.         }
  406.         return result;
  407.     }

  408.     /** {@inheritDoc} */
  409.     @Override
  410.     public Tuple log1p() {
  411.         final Tuple result = new Tuple(field, new double[values.length]);
  412.         for (int i = 0; i < values.length; ++i) {
  413.             result.values[i] = FastMath.log1p(values[i]);
  414.         }
  415.         return result;
  416.     }

  417.     /** {@inheritDoc} */
  418.     @Override
  419.     public Tuple log10() {
  420.         final Tuple result = new Tuple(field, new double[values.length]);
  421.         for (int i = 0; i < values.length; ++i) {
  422.             result.values[i] = FastMath.log10(values[i]);
  423.         }
  424.         return result;
  425.     }

  426.     /** {@inheritDoc} */
  427.     @Override
  428.     public Tuple cos() {
  429.         final Tuple result = new Tuple(field, new double[values.length]);
  430.         for (int i = 0; i < values.length; ++i) {
  431.             result.values[i] = FastMath.cos(values[i]);
  432.         }
  433.         return result;
  434.     }

  435.     /** {@inheritDoc} */
  436.     @Override
  437.     public Tuple sin() {
  438.         final Tuple result = new Tuple(field, new double[values.length]);
  439.         for (int i = 0; i < values.length; ++i) {
  440.             result.values[i] = FastMath.sin(values[i]);
  441.         }
  442.         return result;
  443.     }

  444.     /** {@inheritDoc} */
  445.     @Override
  446.     public FieldSinCos<Tuple> sinCos() {
  447.         final Tuple sin = new Tuple(field, new double[values.length]);
  448.         final Tuple cos = new Tuple(field, new double[values.length]);
  449.         for (int i = 0; i < values.length; ++i) {
  450.             final SinCos sc = FastMath.sinCos(values[i]);
  451.             sin.values[i] = sc.sin();
  452.             cos.values[i] = sc.cos();
  453.         }
  454.         return new FieldSinCos<>(sin, cos);
  455.     }

  456.     /** {@inheritDoc} */
  457.     @Override
  458.     public Tuple tan() {
  459.         final Tuple result = new Tuple(field, new double[values.length]);
  460.         for (int i = 0; i < values.length; ++i) {
  461.             result.values[i] = FastMath.tan(values[i]);
  462.         }
  463.         return result;
  464.     }

  465.     /** {@inheritDoc} */
  466.     @Override
  467.     public Tuple acos() {
  468.         final Tuple result = new Tuple(field, new double[values.length]);
  469.         for (int i = 0; i < values.length; ++i) {
  470.             result.values[i] = FastMath.acos(values[i]);
  471.         }
  472.         return result;
  473.     }

  474.     /** {@inheritDoc} */
  475.     @Override
  476.     public Tuple asin() {
  477.         final Tuple result = new Tuple(field, new double[values.length]);
  478.         for (int i = 0; i < values.length; ++i) {
  479.             result.values[i] = FastMath.asin(values[i]);
  480.         }
  481.         return result;
  482.     }

  483.     /** {@inheritDoc} */
  484.     @Override
  485.     public Tuple atan() {
  486.         final Tuple result = new Tuple(field, new double[values.length]);
  487.         for (int i = 0; i < values.length; ++i) {
  488.             result.values[i] = FastMath.atan(values[i]);
  489.         }
  490.         return result;
  491.     }

  492.     /** {@inheritDoc} */
  493.     @Override
  494.     public Tuple atan2(final Tuple x) {
  495.         final Tuple result = new Tuple(field, new double[values.length]);
  496.         for (int i = 0; i < values.length; ++i) {
  497.             result.values[i] = FastMath.atan2(values[i], x.values[i]);
  498.         }
  499.         return result;
  500.     }

  501.     /** {@inheritDoc} */
  502.     @Override
  503.     public Tuple cosh() {
  504.         final Tuple result = new Tuple(field, new double[values.length]);
  505.         for (int i = 0; i < values.length; ++i) {
  506.             result.values[i] = FastMath.cosh(values[i]);
  507.         }
  508.         return result;
  509.     }

  510.     /** {@inheritDoc} */
  511.     @Override
  512.     public Tuple sinh() {
  513.         final Tuple result = new Tuple(field, new double[values.length]);
  514.         for (int i = 0; i < values.length; ++i) {
  515.             result.values[i] = FastMath.sinh(values[i]);
  516.         }
  517.         return result;
  518.     }

  519.     /** {@inheritDoc} */
  520.     @Override
  521.     public FieldSinhCosh<Tuple> sinhCosh() {
  522.         final Tuple sinh = new Tuple(field, new double[values.length]);
  523.         final Tuple cosh = new Tuple(field, new double[values.length]);
  524.         for (int i = 0; i < values.length; ++i) {
  525.             final SinhCosh sch = FastMath.sinhCosh(values[i]);
  526.             sinh.values[i] = sch.sinh();
  527.             cosh.values[i] = sch.cosh();
  528.         }
  529.         return new FieldSinhCosh<>(sinh, cosh);
  530.     }

  531.     /** {@inheritDoc} */
  532.     @Override
  533.     public Tuple tanh() {
  534.         final Tuple result = new Tuple(field, new double[values.length]);
  535.         for (int i = 0; i < values.length; ++i) {
  536.             result.values[i] = FastMath.tanh(values[i]);
  537.         }
  538.         return result;
  539.     }

  540.     /** {@inheritDoc} */
  541.     @Override
  542.     public Tuple acosh() {
  543.         final Tuple result = new Tuple(field, new double[values.length]);
  544.         for (int i = 0; i < values.length; ++i) {
  545.             result.values[i] = FastMath.acosh(values[i]);
  546.         }
  547.         return result;
  548.     }

  549.     /** {@inheritDoc} */
  550.     @Override
  551.     public Tuple asinh() {
  552.         final Tuple result = new Tuple(field, new double[values.length]);
  553.         for (int i = 0; i < values.length; ++i) {
  554.             result.values[i] = FastMath.asinh(values[i]);
  555.         }
  556.         return result;
  557.     }

  558.     /** {@inheritDoc} */
  559.     @Override
  560.     public Tuple atanh() {
  561.         final Tuple result = new Tuple(field, new double[values.length]);
  562.         for (int i = 0; i < values.length; ++i) {
  563.             result.values[i] = FastMath.atanh(values[i]);
  564.         }
  565.         return result;
  566.     }

  567.     /** {@inheritDoc} */
  568.     @Override
  569.     public Tuple toDegrees() {
  570.         final Tuple result = new Tuple(field, new double[values.length]);
  571.         for (int i = 0; i < values.length; ++i) {
  572.             result.values[i] = FastMath.toDegrees(values[i]);
  573.         }
  574.         return result;
  575.     }

  576.     /** {@inheritDoc} */
  577.     @Override
  578.     public Tuple toRadians() {
  579.         final Tuple result = new Tuple(field, new double[values.length]);
  580.         for (int i = 0; i < values.length; ++i) {
  581.             result.values[i] = FastMath.toRadians(values[i]);
  582.         }
  583.         return result;
  584.     }

  585.     /** {@inheritDoc} */
  586.     @Override
  587.     public Tuple linearCombination(final Tuple[] a, final Tuple[] b)
  588.         throws MathIllegalArgumentException {
  589.         final Tuple result = new Tuple(field, new double[values.length]);
  590.         MathUtils.checkDimension(a.length, b.length);
  591.         final double[] aDouble = new double[a.length];
  592.         final double[] bDouble = new double[b.length];
  593.         for (int i = 0; i < values.length; ++i) {
  594.             for (int j = 0; j < a.length; ++j) {
  595.                 aDouble[j] = a[j].values[i];
  596.                 bDouble[j] = b[j].values[i];
  597.             }
  598.             result.values[i] = MathArrays.linearCombination(aDouble, bDouble);
  599.         }
  600.         return result;
  601.     }

  602.     /** {@inheritDoc} */
  603.     @Override
  604.     public Tuple linearCombination(final double[] a, final Tuple[] b)
  605.         throws MathIllegalArgumentException {
  606.         final Tuple result = new Tuple(field, new double[values.length]);
  607.         MathUtils.checkDimension(a.length, b.length);
  608.         final double[] bDouble = new double[b.length];
  609.         for (int i = 0; i < values.length; ++i) {
  610.             for (int j = 0; j < a.length; ++j) {
  611.                 bDouble[j] = b[j].values[i];
  612.             }
  613.             result.values[i] = MathArrays.linearCombination(a, bDouble);
  614.         }
  615.         return result;
  616.     }

  617.     /** {@inheritDoc} */
  618.     @Override
  619.     public Tuple linearCombination(final Tuple a1, final Tuple b1,
  620.                                    final Tuple a2, final Tuple b2) {
  621.         final Tuple result = new Tuple(field, new double[values.length]);
  622.         for (int i = 0; i < values.length; ++i) {
  623.             result.values[i] = MathArrays.linearCombination(a1.values[i], b1.values[i],
  624.                                                             a2.values[i], b2.values[i]);
  625.         }
  626.         return result;
  627.     }

  628.     /** {@inheritDoc} */
  629.     @Override
  630.     public Tuple linearCombination(final double a1, final Tuple b1,
  631.                                    final double a2, final Tuple b2) {
  632.         final Tuple result = new Tuple(field, new double[values.length]);
  633.         for (int i = 0; i < values.length; ++i) {
  634.             result.values[i] = MathArrays.linearCombination(a1, b1.values[i],
  635.                                                             a2, b2.values[i]);
  636.         }
  637.         return result;
  638.     }

  639.     /** {@inheritDoc} */
  640.     @Override
  641.     public Tuple linearCombination(final Tuple a1, final Tuple b1,
  642.                                    final Tuple a2, final Tuple b2,
  643.                                    final Tuple a3, final Tuple b3) {
  644.         final Tuple result = new Tuple(field, new double[values.length]);
  645.         for (int i = 0; i < values.length; ++i) {
  646.             result.values[i] = MathArrays.linearCombination(a1.values[i], b1.values[i],
  647.                                                             a2.values[i], b2.values[i],
  648.                                                             a3.values[i], b3.values[i]);
  649.         }
  650.         return result;
  651.     }

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

  665.     /** {@inheritDoc} */
  666.     @Override
  667.     public Tuple linearCombination(final Tuple a1, final Tuple b1,
  668.                                    final Tuple a2, final Tuple b2,
  669.                                    final Tuple a3, final Tuple b3,
  670.                                    final Tuple a4, final Tuple b4) {
  671.         final Tuple result = new Tuple(field, new double[values.length]);
  672.         for (int i = 0; i < values.length; ++i) {
  673.             result.values[i] = MathArrays.linearCombination(a1.values[i], b1.values[i],
  674.                                                             a2.values[i], b2.values[i],
  675.                                                             a3.values[i], b3.values[i],
  676.                                                             a4.values[i], b4.values[i]);
  677.         }
  678.         return result;
  679.     }

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

  695.     /** {@inheritDoc} */
  696.     @Override
  697.     public Tuple getPi() {
  698.         final Tuple result = new Tuple(field, new double[values.length]);
  699.         Arrays.fill(result.values, FastMath.PI);
  700.         return result;
  701.     }

  702.     /** Field for {link Tuple} instances.
  703.      */
  704.     private static class TupleField implements Field<Tuple> {

  705.         /** Constant function evaluating to 0.0. */
  706.         private final Tuple zero;

  707.         /** Constant function evaluating to 1.0. */
  708.         private final Tuple one;

  709.         /** Simple constructor.
  710.          * @param dimension dimension of the tuple
  711.          */
  712.         TupleField(final int dimension) {
  713.             final double[] zeroData = new double[dimension];
  714.             final double[] oneData  = new double[dimension];
  715.             Arrays.fill(oneData, 1.0);
  716.             this.zero = new Tuple(this, zeroData);
  717.             this.one  = new Tuple(this, oneData);
  718.         }

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

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

  729.         /** {@inheritDoc} */
  730.         @Override
  731.         public Class<Tuple> getRuntimeClass() {
  732.             return Tuple.class;
  733.         }

  734.         /** {@inheritDoc} */
  735.         @Override
  736.         public boolean equals(final Object other) {
  737.             if (other instanceof TupleField) {
  738.                 return zero.getDimension() == ((TupleField) other).zero.getDimension();
  739.             } else {
  740.                 return false;
  741.             }
  742.         }

  743.         /** {@inheritDoc} */
  744.         @Override
  745.         public int hashCode() {
  746.             return 0x6672493d ^ zero.getDimension();
  747.         }

  748.     }

  749. }