ArrayFieldVector.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) 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 ASF 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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.linear;

  22. import java.io.Serializable;
  23. import java.util.Arrays;

  24. import org.hipparchus.Field;
  25. import org.hipparchus.FieldElement;
  26. import org.hipparchus.exception.LocalizedCoreFormats;
  27. import org.hipparchus.exception.MathIllegalArgumentException;
  28. import org.hipparchus.exception.MathRuntimeException;
  29. import org.hipparchus.exception.NullArgumentException;
  30. import org.hipparchus.util.MathArrays;
  31. import org.hipparchus.util.MathUtils;

  32. /**
  33.  * This class implements the {@link FieldVector} interface with a {@link FieldElement} array.
  34.  * @param <T> the type of the field elements
  35.  */
  36. public class ArrayFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable {
  37.     /** Serializable version identifier. */
  38.     private static final long serialVersionUID = 7648186910365927050L;

  39.     /** Entries of the vector. */
  40.     private T[] data;

  41.     /** Field to which the elements belong. */
  42.     private final Field<T> field;

  43.     /**
  44.      * Build a 0-length vector.
  45.      * Zero-length vectors may be used to initialize construction of vectors
  46.      * by data gathering. We start with zero-length and use either the {@link
  47.      * #ArrayFieldVector(FieldVector, FieldVector)} constructor
  48.      * or one of the {@code append} methods ({@link #add(FieldVector)} or
  49.      * {@link #append(ArrayFieldVector)}) to gather data into this vector.
  50.      *
  51.      * @param field field to which the elements belong
  52.      */
  53.     public ArrayFieldVector(final Field<T> field) {
  54.         this(field, 0);
  55.     }

  56.     /**
  57.      * Construct a vector of zeroes.
  58.      *
  59.      * @param field Field to which the elements belong.
  60.      * @param size Size of the vector.
  61.      */
  62.     public ArrayFieldVector(Field<T> field, int size) {
  63.         this.field = field;
  64.         this.data  = MathArrays.buildArray(field, size);
  65.     }

  66.     /**
  67.      * Construct a vector with preset values.
  68.      *
  69.      * @param size Size of the vector.
  70.      * @param preset All entries will be set with this value.
  71.      */
  72.     public ArrayFieldVector(int size, T preset) {
  73.         this(preset.getField(), size);
  74.         Arrays.fill(data, preset);
  75.     }

  76.     /**
  77.      * Construct a vector from an array, copying the input array.
  78.      * This constructor needs a non-empty {@code d} array to retrieve
  79.      * the field from its first element. This implies it cannot build
  80.      * 0 length vectors. To build vectors from any size, one should
  81.      * use the {@link #ArrayFieldVector(Field, FieldElement[])} constructor.
  82.      *
  83.      * @param d Array.
  84.      * @throws NullArgumentException if {@code d} is {@code null}.
  85.      * @throws MathIllegalArgumentException if {@code d} is empty.
  86.      * @see #ArrayFieldVector(Field, FieldElement[])
  87.      */
  88.     public ArrayFieldVector(T[] d)
  89.             throws MathIllegalArgumentException, NullArgumentException {
  90.         MathUtils.checkNotNull(d);
  91.         try {
  92.             field = d[0].getField();
  93.             data = d.clone();
  94.         } catch (ArrayIndexOutOfBoundsException e) {
  95.             throw new MathIllegalArgumentException(e, LocalizedCoreFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
  96.         }
  97.     }

  98.     /**
  99.      * Construct a vector from an array, copying the input array.
  100.      *
  101.      * @param field Field to which the elements belong.
  102.      * @param d Array.
  103.      * @throws NullArgumentException if {@code d} is {@code null}.
  104.      * @see #ArrayFieldVector(FieldElement[])
  105.      */
  106.     public ArrayFieldVector(Field<T> field, T[] d)
  107.             throws NullArgumentException {
  108.         MathUtils.checkNotNull(d);
  109.         this.field = field;
  110.         data = d.clone();
  111.     }

  112.     /**
  113.      * Create a new ArrayFieldVector using the input array as the underlying
  114.      * data array.
  115.      * If an array is built specially in order to be embedded in a
  116.      * ArrayFieldVector and not used directly, the {@code copyArray} may be
  117.      * set to {@code false}. This will prevent the copying and improve
  118.      * performance as no new array will be built and no data will be copied.
  119.      * This constructor needs a non-empty {@code d} array to retrieve
  120.      * the field from its first element. This implies it cannot build
  121.      * 0 length vectors. To build vectors from any size, one should
  122.      * use the {@link #ArrayFieldVector(Field, FieldElement[], boolean)}
  123.      * constructor.
  124.      *
  125.      * @param d Data for the new vector.
  126.      * @param copyArray If {@code true}, the input array will be copied,
  127.      * otherwise it will be referenced.
  128.      * @throws NullArgumentException if {@code d} is {@code null}.
  129.      * @throws MathIllegalArgumentException if {@code d} is empty.
  130.      * @see #ArrayFieldVector(FieldElement[])
  131.      * @see #ArrayFieldVector(Field, FieldElement[], boolean)
  132.      */
  133.     public ArrayFieldVector(T[] d, boolean copyArray)
  134.             throws MathIllegalArgumentException, NullArgumentException {
  135.         MathUtils.checkNotNull(d);
  136.         if (d.length == 0) {
  137.             throw new MathIllegalArgumentException(LocalizedCoreFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
  138.         }
  139.         field = d[0].getField();
  140.         data = copyArray ? d.clone() : d;
  141.     }

  142.     /**
  143.      * Create a new ArrayFieldVector using the input array as the underlying
  144.      * data array.
  145.      * If an array is built specially in order to be embedded in a
  146.      * ArrayFieldVector and not used directly, the {@code copyArray} may be
  147.      * set to {@code false}. This will prevent the copying and improve
  148.      * performance as no new array will be built and no data will be copied.
  149.      *
  150.      * @param field Field to which the elements belong.
  151.      * @param d Data for the new vector.
  152.      * @param copyArray If {@code true}, the input array will be copied,
  153.      * otherwise it will be referenced.
  154.      * @throws NullArgumentException if {@code d} is {@code null}.
  155.      * @see #ArrayFieldVector(FieldElement[], boolean)
  156.      */
  157.     public ArrayFieldVector(Field<T> field, T[] d, boolean copyArray)
  158.             throws NullArgumentException {
  159.         MathUtils.checkNotNull(d);
  160.         this.field = field;
  161.         data = copyArray ? d.clone() :  d;
  162.     }

  163.     /**
  164.      * Construct a vector from part of a array.
  165.      *
  166.      * @param d Array.
  167.      * @param pos Position of the first entry.
  168.      * @param size Number of entries to copy.
  169.      * @throws NullArgumentException if {@code d} is {@code null}.
  170.      * @throws MathIllegalArgumentException if the size of {@code d} is less
  171.      * than {@code pos + size}.
  172.      */
  173.     public ArrayFieldVector(T[] d, int pos, int size)
  174.             throws MathIllegalArgumentException, NullArgumentException {
  175.         MathUtils.checkNotNull(d);
  176.         if (d.length < pos + size) {
  177.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
  178.                                                    pos + size, d.length);
  179.         }
  180.         field = d[0].getField();
  181.         data = MathArrays.buildArray(field, size);
  182.         System.arraycopy(d, pos, data, 0, size);
  183.     }

  184.     /**
  185.      * Construct a vector from part of a array.
  186.      *
  187.      * @param field Field to which the elements belong.
  188.      * @param d Array.
  189.      * @param pos Position of the first entry.
  190.      * @param size Number of entries to copy.
  191.      * @throws NullArgumentException if {@code d} is {@code null}.
  192.      * @throws MathIllegalArgumentException if the size of {@code d} is less
  193.      * than {@code pos + size}.
  194.      */
  195.     public ArrayFieldVector(Field<T> field, T[] d, int pos, int size)
  196.             throws MathIllegalArgumentException, NullArgumentException {
  197.         MathUtils.checkNotNull(d);
  198.         if (d.length < pos + size) {
  199.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
  200.                                                    pos + size, d.length);
  201.         }
  202.         this.field = field;
  203.         data = MathArrays.buildArray(field, size);
  204.         System.arraycopy(d, pos, data, 0, size);
  205.     }

  206.     /**
  207.      * Construct a vector from another vector, using a deep copy.
  208.      *
  209.      * @param v Vector to copy.
  210.      * @throws NullArgumentException if {@code v} is {@code null}.
  211.      */
  212.     public ArrayFieldVector(FieldVector<T> v)
  213.             throws NullArgumentException {
  214.         MathUtils.checkNotNull(v);
  215.         field = v.getField();
  216.         data = MathArrays.buildArray(field, v.getDimension());
  217.         for (int i = 0; i < data.length; ++i) {
  218.             data[i] = v.getEntry(i);
  219.         }
  220.     }

  221.     /**
  222.      * Construct a vector from another vector, using a deep copy.
  223.      *
  224.      * @param v Vector to copy.
  225.      * @throws NullArgumentException if {@code v} is {@code null}.
  226.      */
  227.     public ArrayFieldVector(ArrayFieldVector<T> v)
  228.             throws NullArgumentException {
  229.         MathUtils.checkNotNull(v);
  230.         field = v.getField();
  231.         data = v.data.clone();
  232.     }

  233.     /**
  234.      * Construct a vector from another vector.
  235.      *
  236.      * @param v Vector to copy.
  237.      * @param deep If {@code true} perform a deep copy, otherwise perform
  238.      * a shallow copy
  239.      * @throws NullArgumentException if {@code v} is {@code null}.
  240.      */
  241.     public ArrayFieldVector(ArrayFieldVector<T> v, boolean deep)
  242.             throws NullArgumentException {
  243.         MathUtils.checkNotNull(v);
  244.         field = v.getField();
  245.         data = deep ? v.data.clone() : v.data;
  246.     }

  247.     /**
  248.      * Construct a vector by appending one vector to another vector.
  249.      *
  250.      * @param v1 First vector (will be put in front of the new vector).
  251.      * @param v2 Second vector (will be put at back of the new vector).
  252.      * @throws NullArgumentException if {@code v1} or {@code v2} is
  253.      * {@code null}.
  254.      */
  255.     public ArrayFieldVector(FieldVector<T> v1, FieldVector<T> v2)
  256.             throws NullArgumentException {
  257.         MathUtils.checkNotNull(v1);
  258.         MathUtils.checkNotNull(v2);
  259.         field = v1.getField();
  260.         final T[] v1Data =
  261.                 (v1 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v1).data : v1.toArray();
  262.         final T[] v2Data =
  263.                 (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray();
  264.         data = MathArrays.buildArray(field, v1Data.length + v2Data.length);
  265.         System.arraycopy(v1Data, 0, data, 0, v1Data.length);
  266.         System.arraycopy(v2Data, 0, data, v1Data.length, v2Data.length);
  267.     }

  268.     /**
  269.      * Construct a vector by appending one vector to another vector.
  270.      *
  271.      * @param v1 First vector (will be put in front of the new vector).
  272.      * @param v2 Second vector (will be put at back of the new vector).
  273.      * @throws NullArgumentException if {@code v1} or {@code v2} is
  274.      * {@code null}.
  275.      */
  276.     public ArrayFieldVector(FieldVector<T> v1, T[] v2)
  277.             throws NullArgumentException {
  278.         MathUtils.checkNotNull(v1);
  279.         MathUtils.checkNotNull(v2);
  280.         field = v1.getField();
  281.         final T[] v1Data =
  282.                 (v1 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v1).data : v1.toArray();
  283.         data = MathArrays.buildArray(field, v1Data.length + v2.length);
  284.         System.arraycopy(v1Data, 0, data, 0, v1Data.length);
  285.         System.arraycopy(v2, 0, data, v1Data.length, v2.length);
  286.     }

  287.     /**
  288.      * Construct a vector by appending one vector to another vector.
  289.      *
  290.      * @param v1 First vector (will be put in front of the new vector).
  291.      * @param v2 Second vector (will be put at back of the new vector).
  292.      * @throws NullArgumentException if {@code v1} or {@code v2} is
  293.      * {@code null}.
  294.      */
  295.     public ArrayFieldVector(T[] v1, FieldVector<T> v2)
  296.             throws NullArgumentException {
  297.         MathUtils.checkNotNull(v1);
  298.         MathUtils.checkNotNull(v2);
  299.         field = v2.getField();
  300.         final T[] v2Data =
  301.                 (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray();
  302.         data = MathArrays.buildArray(field, v1.length + v2Data.length);
  303.         System.arraycopy(v1, 0, data, 0, v1.length);
  304.         System.arraycopy(v2Data, 0, data, v1.length, v2Data.length);
  305.     }

  306.     /**
  307.      * Construct a vector by appending one vector to another vector.
  308.      * This constructor needs at least one non-empty array to retrieve
  309.      * the field from its first element. This implies it cannot build
  310.      * 0 length vectors. To build vectors from any size, one should
  311.      * use the {@link #ArrayFieldVector(Field, FieldElement[], FieldElement[])}
  312.      * constructor.
  313.      *
  314.      * @param v1 First vector (will be put in front of the new vector).
  315.      * @param v2 Second vector (will be put at back of the new vector).
  316.      * @throws NullArgumentException if {@code v1} or {@code v2} is
  317.      * {@code null}.
  318.      * @throws MathIllegalArgumentException if both arrays are empty.
  319.      * @see #ArrayFieldVector(Field, FieldElement[], FieldElement[])
  320.      */
  321.     public ArrayFieldVector(T[] v1, T[] v2)
  322.             throws MathIllegalArgumentException, NullArgumentException {
  323.         MathUtils.checkNotNull(v1);
  324.         MathUtils.checkNotNull(v2);
  325.         if (v1.length + v2.length == 0) {
  326.             throw new MathIllegalArgumentException(LocalizedCoreFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
  327.         }
  328.         data = MathArrays.buildArray(v1[0].getField(), v1.length + v2.length);
  329.         System.arraycopy(v1, 0, data, 0, v1.length);
  330.         System.arraycopy(v2, 0, data, v1.length, v2.length);
  331.         field = data[0].getField();
  332.     }

  333.     /**
  334.      * Construct a vector by appending one vector to another vector.
  335.      *
  336.      * @param field Field to which the elements belong.
  337.      * @param v1 First vector (will be put in front of the new vector).
  338.      * @param v2 Second vector (will be put at back of the new vector).
  339.      * @throws NullArgumentException if {@code v1} or {@code v2} is
  340.      * {@code null}.
  341.      * @throws MathIllegalArgumentException if both arrays are empty.
  342.      * @see #ArrayFieldVector(FieldElement[], FieldElement[])
  343.      */
  344.     public ArrayFieldVector(Field<T> field, T[] v1, T[] v2)
  345.             throws MathIllegalArgumentException, NullArgumentException {
  346.         MathUtils.checkNotNull(v1);
  347.         MathUtils.checkNotNull(v2);
  348.         if (v1.length + v2.length == 0) {
  349.             throw new MathIllegalArgumentException(LocalizedCoreFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
  350.         }
  351.         data = MathArrays.buildArray(field, v1.length + v2.length);
  352.         System.arraycopy(v1, 0, data, 0, v1.length);
  353.         System.arraycopy(v2, 0, data, v1.length, v2.length);
  354.         this.field = field;
  355.     }

  356.     /** {@inheritDoc} */
  357.     @Override
  358.     public Field<T> getField() {
  359.         return field;
  360.     }

  361.     /** {@inheritDoc} */
  362.     @Override
  363.     public FieldVector<T> copy() {
  364.         return new ArrayFieldVector<>(this, true);
  365.     }

  366.     /** {@inheritDoc} */
  367.     @Override
  368.     public FieldVector<T> add(FieldVector<T> v)
  369.         throws MathIllegalArgumentException {
  370.         if (v instanceof ArrayFieldVector) {
  371.             return add((ArrayFieldVector<T>) v);
  372.         } else {
  373.             checkVectorDimensions(v);
  374.             T[] out = MathArrays.buildArray(field, data.length);
  375.             for (int i = 0; i < data.length; i++) {
  376.                 out[i] = data[i].add(v.getEntry(i));
  377.             }
  378.             return new ArrayFieldVector<>(field, out, false);
  379.         }
  380.     }

  381.     /**
  382.      * Compute the sum of {@code this} and {@code v}.
  383.      * @param v vector to be added
  384.      * @return {@code this + v}
  385.      * @throws MathIllegalArgumentException if {@code v} is not the same size as
  386.      * {@code this}
  387.      */
  388.     public ArrayFieldVector<T> add(ArrayFieldVector<T> v)
  389.         throws MathIllegalArgumentException {
  390.         checkVectorDimensions(v.data.length);
  391.         T[] out = MathArrays.buildArray(field, data.length);
  392.         for (int i = 0; i < data.length; i++) {
  393.             out[i] = data[i].add(v.data[i]);
  394.         }
  395.         return new ArrayFieldVector<>(field, out, false);
  396.     }

  397.     /** {@inheritDoc} */
  398.     @Override
  399.     public FieldVector<T> subtract(FieldVector<T> v)
  400.         throws MathIllegalArgumentException {
  401.         if (v instanceof ArrayFieldVector) {
  402.             return subtract((ArrayFieldVector<T>) v);
  403.         } else {
  404.             checkVectorDimensions(v);
  405.             T[] out = MathArrays.buildArray(field, data.length);
  406.             for (int i = 0; i < data.length; i++) {
  407.                 out[i] = data[i].subtract(v.getEntry(i));
  408.             }
  409.             return new ArrayFieldVector<>(field, out, false);
  410.         }
  411.     }

  412.     /**
  413.      * Compute {@code this} minus {@code v}.
  414.      * @param v vector to be subtracted
  415.      * @return {@code this - v}
  416.      * @throws MathIllegalArgumentException if {@code v} is not the same size as
  417.      * {@code this}
  418.      */
  419.     public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v)
  420.         throws MathIllegalArgumentException {
  421.         checkVectorDimensions(v.data.length);
  422.         T[] out = MathArrays.buildArray(field, data.length);
  423.         for (int i = 0; i < data.length; i++) {
  424.             out[i] = data[i].subtract(v.data[i]);
  425.         }
  426.         return new ArrayFieldVector<>(field, out, false);
  427.     }

  428.     /** {@inheritDoc} */
  429.     @Override
  430.     public FieldVector<T> mapAdd(T d) throws NullArgumentException {
  431.         T[] out = MathArrays.buildArray(field, data.length);
  432.         for (int i = 0; i < data.length; i++) {
  433.             out[i] = data[i].add(d);
  434.         }
  435.         return new ArrayFieldVector<>(field, out, false);
  436.     }

  437.     /** {@inheritDoc} */
  438.     @Override
  439.     public FieldVector<T> mapAddToSelf(T d) throws NullArgumentException {
  440.         for (int i = 0; i < data.length; i++) {
  441.             data[i] = data[i].add(d);
  442.         }
  443.         return this;
  444.     }

  445.     /** {@inheritDoc} */
  446.     @Override
  447.     public FieldVector<T> mapSubtract(T d) throws NullArgumentException {
  448.         T[] out = MathArrays.buildArray(field, data.length);
  449.         for (int i = 0; i < data.length; i++) {
  450.             out[i] = data[i].subtract(d);
  451.         }
  452.         return new ArrayFieldVector<>(field, out, false);
  453.     }

  454.     /** {@inheritDoc} */
  455.     @Override
  456.     public FieldVector<T> mapSubtractToSelf(T d) throws NullArgumentException {
  457.         for (int i = 0; i < data.length; i++) {
  458.             data[i] = data[i].subtract(d);
  459.         }
  460.         return this;
  461.     }

  462.     /** {@inheritDoc} */
  463.     @Override
  464.     public FieldVector<T> mapMultiply(T d) throws NullArgumentException {
  465.         T[] out = MathArrays.buildArray(field, data.length);
  466.         for (int i = 0; i < data.length; i++) {
  467.             out[i] = data[i].multiply(d);
  468.         }
  469.         return new ArrayFieldVector<>(field, out, false);
  470.     }

  471.     /** {@inheritDoc} */
  472.     @Override
  473.     public FieldVector<T> mapMultiplyToSelf(T d) throws NullArgumentException {
  474.         for (int i = 0; i < data.length; i++) {
  475.             data[i] = data[i].multiply(d);
  476.         }
  477.         return this;
  478.     }

  479.     /** {@inheritDoc} */
  480.     @Override
  481.     public FieldVector<T> mapDivide(T d)
  482.         throws NullArgumentException, MathRuntimeException {
  483.         MathUtils.checkNotNull(d);
  484.         T[] out = MathArrays.buildArray(field, data.length);
  485.         for (int i = 0; i < data.length; i++) {
  486.             out[i] = data[i].divide(d);
  487.         }
  488.         return new ArrayFieldVector<>(field, out, false);
  489.     }

  490.     /** {@inheritDoc} */
  491.     @Override
  492.     public FieldVector<T> mapDivideToSelf(T d)
  493.         throws NullArgumentException, MathRuntimeException {
  494.         MathUtils.checkNotNull(d);
  495.         for (int i = 0; i < data.length; i++) {
  496.             data[i] = data[i].divide(d);
  497.         }
  498.         return this;
  499.     }

  500.     /** {@inheritDoc} */
  501.     @Override
  502.     public FieldVector<T> mapInv() throws MathRuntimeException {
  503.         T[] out = MathArrays.buildArray(field, data.length);
  504.         final T one = field.getOne();
  505.         for (int i = 0; i < data.length; i++) {
  506.             try {
  507.                 out[i] = one.divide(data[i]);
  508.             } catch (final MathRuntimeException e) {
  509.                 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
  510.             }
  511.         }
  512.         return new ArrayFieldVector<>(field, out, false);
  513.     }

  514.     /** {@inheritDoc} */
  515.     @Override
  516.     public FieldVector<T> mapInvToSelf() throws MathRuntimeException {
  517.         final T one = field.getOne();
  518.         for (int i = 0; i < data.length; i++) {
  519.             try {
  520.                 data[i] = one.divide(data[i]);
  521.             } catch (final MathRuntimeException e) {
  522.                 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
  523.             }
  524.         }
  525.         return this;
  526.     }

  527.     /** {@inheritDoc} */
  528.     @Override
  529.     public FieldVector<T> ebeMultiply(FieldVector<T> v)
  530.         throws MathIllegalArgumentException {
  531.         if (v instanceof ArrayFieldVector) {
  532.             return ebeMultiply((ArrayFieldVector<T>) v);
  533.         } else {
  534.             checkVectorDimensions(v);
  535.             T[] out = MathArrays.buildArray(field, data.length);
  536.             for (int i = 0; i < data.length; i++) {
  537.                 out[i] = data[i].multiply(v.getEntry(i));
  538.             }
  539.             return new ArrayFieldVector<>(field, out, false);
  540.         }
  541.     }

  542.     /**
  543.      * Element-by-element multiplication.
  544.      * @param v vector by which instance elements must be multiplied
  545.      * @return a vector containing {@code this[i] * v[i]} for all {@code i}
  546.      * @throws MathIllegalArgumentException if {@code v} is not the same size as
  547.      * {@code this}
  548.      */
  549.     public ArrayFieldVector<T> ebeMultiply(ArrayFieldVector<T> v)
  550.         throws MathIllegalArgumentException {
  551.         checkVectorDimensions(v.data.length);
  552.         T[] out = MathArrays.buildArray(field, data.length);
  553.         for (int i = 0; i < data.length; i++) {
  554.             out[i] = data[i].multiply(v.data[i]);
  555.         }
  556.         return new ArrayFieldVector<>(field, out, false);
  557.     }

  558.     /** {@inheritDoc} */
  559.     @Override
  560.     public FieldVector<T> ebeDivide(FieldVector<T> v)
  561.         throws MathRuntimeException {
  562.         if (v instanceof ArrayFieldVector) {
  563.             return ebeDivide((ArrayFieldVector<T>) v);
  564.         } else {
  565.             checkVectorDimensions(v);
  566.             T[] out = MathArrays.buildArray(field, data.length);
  567.             for (int i = 0; i < data.length; i++) {
  568.                 try {
  569.                     out[i] = data[i].divide(v.getEntry(i));
  570.                 } catch (final MathRuntimeException e) {
  571.                     throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
  572.                 }
  573.             }
  574.             return new ArrayFieldVector<>(field, out, false);
  575.         }
  576.     }

  577.     /**
  578.      * Element-by-element division.
  579.      * @param v vector by which instance elements must be divided
  580.      * @return a vector containing {@code this[i] / v[i]} for all {@code i}
  581.      * @throws MathIllegalArgumentException if {@code v} is not the same size as
  582.      * {@code this}
  583.      * @throws MathRuntimeException if one entry of {@code v} is zero.
  584.      */
  585.     public ArrayFieldVector<T> ebeDivide(ArrayFieldVector<T> v)
  586.         throws MathIllegalArgumentException, MathRuntimeException {
  587.         checkVectorDimensions(v.data.length);
  588.         T[] out = MathArrays.buildArray(field, data.length);
  589.         for (int i = 0; i < data.length; i++) {
  590.             try {
  591.                 out[i] = data[i].divide(v.data[i]);
  592.             } catch (final MathRuntimeException e) {
  593.                 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
  594.             }
  595.         }
  596.         return new ArrayFieldVector<>(field, out, false);
  597.     }

  598.     /**
  599.      * Returns a reference to the underlying data array.
  600.      * <p>Does not make a fresh copy of the underlying data.</p>
  601.      * @return array of entries
  602.      */
  603.     public T[] getDataRef() {
  604.         return data; // NOPMD - returning an internal array is intentional and documented here
  605.     }

  606.     /** {@inheritDoc} */
  607.     @Override
  608.     public T dotProduct(FieldVector<T> v)
  609.         throws MathIllegalArgumentException {
  610.         if (v instanceof ArrayFieldVector) {
  611.             return dotProduct((ArrayFieldVector<T>) v);
  612.         } else {
  613.             checkVectorDimensions(v);
  614.             T dot = field.getZero();
  615.             for (int i = 0; i < data.length; i++) {
  616.                 dot = dot.add(data[i].multiply(v.getEntry(i)));
  617.             }
  618.             return dot;
  619.         }
  620.     }

  621.     /**
  622.      * Compute the dot product.
  623.      * @param v vector with which dot product should be computed
  624.      * @return the scalar dot product of {@code this} and {@code v}
  625.      * @throws MathIllegalArgumentException if {@code v} is not the same size as
  626.      * {@code this}
  627.      */
  628.     public T dotProduct(ArrayFieldVector<T> v)
  629.         throws MathIllegalArgumentException {
  630.         checkVectorDimensions(v.data.length);
  631.         T dot = field.getZero();
  632.         for (int i = 0; i < data.length; i++) {
  633.             dot = dot.add(data[i].multiply(v.data[i]));
  634.         }
  635.         return dot;
  636.     }

  637.     /** {@inheritDoc} */
  638.     @Override
  639.     public FieldVector<T> projection(FieldVector<T> v)
  640.         throws MathRuntimeException {
  641.         return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
  642.     }

  643.     /** Find the orthogonal projection of this vector onto another vector.
  644.      * @param v vector onto which {@code this} must be projected
  645.      * @return projection of {@code this} onto {@code v}
  646.      * @throws MathIllegalArgumentException if {@code v} is not the same size as
  647.      * {@code this}
  648.      * @throws MathRuntimeException if {@code v} is the null vector.
  649.      */
  650.     public ArrayFieldVector<T> projection(ArrayFieldVector<T> v)
  651.         throws MathIllegalArgumentException, MathRuntimeException {
  652.         return (ArrayFieldVector<T>) v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
  653.     }

  654.     /** {@inheritDoc} */
  655.     @Override
  656.     public FieldMatrix<T> outerProduct(FieldVector<T> v) {
  657.         if (v instanceof ArrayFieldVector) {
  658.             return outerProduct((ArrayFieldVector<T>) v);
  659.         } else {
  660.             final int m = data.length;
  661.             final int n = v.getDimension();
  662.             final FieldMatrix<T> out = new Array2DRowFieldMatrix<>(field, m, n);
  663.             for (int i = 0; i < m; i++) {
  664.                 for (int j = 0; j < n; j++) {
  665.                     out.setEntry(i, j, data[i].multiply(v.getEntry(j)));
  666.                 }
  667.             }
  668.             return out;
  669.         }
  670.     }

  671.     /**
  672.      * Compute the outer product.
  673.      * @param v vector with which outer product should be computed
  674.      * @return the matrix outer product between instance and v
  675.      */
  676.     public FieldMatrix<T> outerProduct(ArrayFieldVector<T> v) {
  677.         final int m = data.length;
  678.         final int n = v.data.length;
  679.         final FieldMatrix<T> out = new Array2DRowFieldMatrix<>(field, m, n);
  680.         for (int i = 0; i < m; i++) {
  681.             for (int j = 0; j < n; j++) {
  682.                 out.setEntry(i, j, data[i].multiply(v.data[j]));
  683.             }
  684.         }
  685.         return out;
  686.     }

  687.     /** {@inheritDoc} */
  688.     @Override
  689.     public T getEntry(int index) {
  690.         return data[index];
  691.     }

  692.     /** {@inheritDoc} */
  693.     @Override
  694.     public int getDimension() {
  695.         return data.length;
  696.     }

  697.     /** {@inheritDoc} */
  698.     @Override
  699.     public FieldVector<T> append(FieldVector<T> v) {
  700.         if (v instanceof ArrayFieldVector) {
  701.             return append((ArrayFieldVector<T>) v);
  702.         } else {
  703.             return new ArrayFieldVector<>(this, new ArrayFieldVector<>(v));
  704.         }
  705.     }

  706.     /**
  707.      * Construct a vector by appending a vector to this vector.
  708.      * @param v vector to append to this one.
  709.      * @return a new vector
  710.      */
  711.     public ArrayFieldVector<T> append(ArrayFieldVector<T> v) {
  712.         return new ArrayFieldVector<>(this, v);
  713.     }

  714.     /** {@inheritDoc} */
  715.     @Override
  716.     public FieldVector<T> append(T in) {
  717.         final T[] out = MathArrays.buildArray(field, data.length + 1);
  718.         System.arraycopy(data, 0, out, 0, data.length);
  719.         out[data.length] = in;
  720.         return new ArrayFieldVector<>(field, out, false);
  721.     }

  722.     /** {@inheritDoc} */
  723.     @Override
  724.     public FieldVector<T> getSubVector(int index, int n)
  725.         throws MathIllegalArgumentException {
  726.         if (n < 0) {
  727.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
  728.         }
  729.         ArrayFieldVector<T> out = new ArrayFieldVector<>(field, n);
  730.         try {
  731.             System.arraycopy(data, index, out.data, 0, n);
  732.         } catch (IndexOutOfBoundsException e) {
  733.             checkIndex(index);
  734.             checkIndex(index + n - 1);
  735.         }
  736.         return out;
  737.     }

  738.     /** {@inheritDoc} */
  739.     @Override
  740.     public void setEntry(int index, T value) {
  741.         try {
  742.             data[index] = value;
  743.         } catch (IndexOutOfBoundsException e) {
  744.             checkIndex(index);
  745.         }
  746.     }

  747.     /** {@inheritDoc} */
  748.     @Override
  749.     public void setSubVector(int index, FieldVector<T> v) throws MathIllegalArgumentException {
  750.         try {
  751.             if (v instanceof ArrayFieldVector) {
  752.                 set(index, (ArrayFieldVector<T>) v);
  753.             } else {
  754.                 for (int i = index; i < index + v.getDimension(); ++i) {
  755.                     data[i] = v.getEntry(i-index);
  756.                 }
  757.             }
  758.         } catch (IndexOutOfBoundsException e) {
  759.             checkIndex(index);
  760.             checkIndex(index + v.getDimension() - 1);
  761.         }
  762.     }

  763.     /**
  764.      * Set a set of consecutive elements.
  765.      *
  766.      * @param index index of first element to be set.
  767.      * @param v vector containing the values to set.
  768.      * @throws MathIllegalArgumentException if the index is invalid.
  769.      */
  770.     public void set(int index, ArrayFieldVector<T> v) throws MathIllegalArgumentException {
  771.         try {
  772.             System.arraycopy(v.data, 0, data, index, v.data.length);
  773.         } catch (IndexOutOfBoundsException e) {
  774.             checkIndex(index);
  775.             checkIndex(index + v.data.length - 1);
  776.         }
  777.     }

  778.     /** {@inheritDoc} */
  779.     @Override
  780.     public void set(T value) {
  781.         Arrays.fill(data, value);
  782.     }

  783.     /** {@inheritDoc} */
  784.     @Override
  785.     public T[] toArray(){
  786.         return data.clone();
  787.     }

  788.     /**
  789.      * Check if instance and specified vectors have the same dimension.
  790.      * @param v vector to compare instance with
  791.      * @exception MathIllegalArgumentException if the vectors do not
  792.      * have the same dimensions
  793.      */
  794.     protected void checkVectorDimensions(FieldVector<T> v)
  795.         throws MathIllegalArgumentException {
  796.         checkVectorDimensions(v.getDimension());
  797.     }

  798.     /**
  799.      * Check if instance dimension is equal to some expected value.
  800.      *
  801.      * @param n Expected dimension.
  802.      * @throws MathIllegalArgumentException if the dimension is not equal to the
  803.      * size of {@code this} vector.
  804.      */
  805.     protected void checkVectorDimensions(int n)
  806.         throws MathIllegalArgumentException {
  807.         if (data.length != n) {
  808.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  809.                                                    data.length, n);
  810.         }
  811.     }

  812.     /**
  813.      * Visits (but does not alter) all entries of this vector in default order
  814.      * (increasing index).
  815.      *
  816.      * @param visitor the visitor to be used to process the entries of this
  817.      * vector
  818.      * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
  819.      * at the end of the walk
  820.      */
  821.     public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor) {
  822.         final int dim = getDimension();
  823.         visitor.start(dim, 0, dim - 1);
  824.         for (int i = 0; i < dim; i++) {
  825.             visitor.visit(i, getEntry(i));
  826.         }
  827.         return visitor.end();
  828.     }

  829.     /**
  830.      * Visits (but does not alter) some entries of this vector in default order
  831.      * (increasing index).
  832.      *
  833.      * @param visitor visitor to be used to process the entries of this vector
  834.      * @param start the index of the first entry to be visited
  835.      * @param end the index of the last entry to be visited (inclusive)
  836.      * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
  837.      * at the end of the walk
  838.      * @throws MathIllegalArgumentException if {@code end < start}.
  839.      * @throws MathIllegalArgumentException if the indices are not valid.
  840.      */
  841.     public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor,
  842.                                 final int start, final int end)
  843.         throws MathIllegalArgumentException {
  844.         checkIndices(start, end);
  845.         visitor.start(getDimension(), start, end);
  846.         for (int i = start; i <= end; i++) {
  847.             visitor.visit(i, getEntry(i));
  848.         }
  849.         return visitor.end();
  850.     }

  851.     /**
  852.      * Visits (but does not alter) all entries of this vector in optimized
  853.      * order. The order in which the entries are visited is selected so as to
  854.      * lead to the most efficient implementation; it might depend on the
  855.      * concrete implementation of this abstract class.
  856.      *
  857.      * @param visitor the visitor to be used to process the entries of this
  858.      * vector
  859.      * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
  860.      * at the end of the walk
  861.      */
  862.     public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor) {
  863.         return walkInDefaultOrder(visitor);
  864.     }

  865.     /**
  866.      * Visits (but does not alter) some entries of this vector in optimized
  867.      * order. The order in which the entries are visited is selected so as to
  868.      * lead to the most efficient implementation; it might depend on the
  869.      * concrete implementation of this abstract class.
  870.      *
  871.      * @param visitor visitor to be used to process the entries of this vector
  872.      * @param start the index of the first entry to be visited
  873.      * @param end the index of the last entry to be visited (inclusive)
  874.      * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
  875.      * at the end of the walk
  876.      * @throws MathIllegalArgumentException if {@code end < start}.
  877.      * @throws MathIllegalArgumentException if the indices are not valid.
  878.      */
  879.     public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor,
  880.                                   final int start, final int end)
  881.         throws MathIllegalArgumentException {
  882.         return walkInDefaultOrder(visitor, start, end);
  883.     }

  884.     /**
  885.      * Visits (and possibly alters) all entries of this vector in default order
  886.      * (increasing index).
  887.      *
  888.      * @param visitor the visitor to be used to process and modify the entries
  889.      * of this vector
  890.      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
  891.      * at the end of the walk
  892.      */
  893.     public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor) {
  894.         final int dim = getDimension();
  895.         visitor.start(dim, 0, dim - 1);
  896.         for (int i = 0; i < dim; i++) {
  897.             setEntry(i, visitor.visit(i, getEntry(i)));
  898.         }
  899.         return visitor.end();
  900.     }

  901.     /**
  902.      * Visits (and possibly alters) some entries of this vector in default order
  903.      * (increasing index).
  904.      *
  905.      * @param visitor visitor to be used to process the entries of this vector
  906.      * @param start the index of the first entry to be visited
  907.      * @param end the index of the last entry to be visited (inclusive)
  908.      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
  909.      * at the end of the walk
  910.      * @throws MathIllegalArgumentException if {@code end < start}.
  911.      * @throws MathIllegalArgumentException if the indices are not valid.
  912.      */
  913.     public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor,
  914.                                 final int start, final int end)
  915.         throws MathIllegalArgumentException {
  916.         checkIndices(start, end);
  917.         visitor.start(getDimension(), start, end);
  918.         for (int i = start; i <= end; i++) {
  919.             setEntry(i, visitor.visit(i, getEntry(i)));
  920.         }
  921.         return visitor.end();
  922.     }

  923.     /**
  924.      * Visits (and possibly alters) all entries of this vector in optimized
  925.      * order. The order in which the entries are visited is selected so as to
  926.      * lead to the most efficient implementation; it might depend on the
  927.      * concrete implementation of this abstract class.
  928.      *
  929.      * @param visitor the visitor to be used to process the entries of this
  930.      * vector
  931.      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
  932.      * at the end of the walk
  933.      */
  934.     public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor) {
  935.         return walkInDefaultOrder(visitor);
  936.     }

  937.     /**
  938.      * Visits (and possibly change) some entries of this vector in optimized
  939.      * order. The order in which the entries are visited is selected so as to
  940.      * lead to the most efficient implementation; it might depend on the
  941.      * concrete implementation of this abstract class.
  942.      *
  943.      * @param visitor visitor to be used to process the entries of this vector
  944.      * @param start the index of the first entry to be visited
  945.      * @param end the index of the last entry to be visited (inclusive)
  946.      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
  947.      * at the end of the walk
  948.      * @throws MathIllegalArgumentException if {@code end < start}.
  949.      * @throws MathIllegalArgumentException if the indices are not valid.
  950.      */
  951.     public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor,
  952.                                   final int start, final int end)
  953.         throws MathIllegalArgumentException {
  954.         return walkInDefaultOrder(visitor, start, end);
  955.     }
  956.     /** {@inheritDoc}
  957.      * @since 2.0
  958.      */
  959.     @Override
  960.     public String toString() {
  961.         final StringBuilder builder = new StringBuilder();
  962.         builder.append('{');
  963.         for (int i = 0; i < data.length; ++i) {
  964.             if (i > 0) {
  965.                 builder.append("; ");
  966.             }
  967.             builder.append(data[i].toString());
  968.         }
  969.         builder.append('}');
  970.         return builder.toString();
  971.     }

  972.     /**
  973.      * Test for the equality of two vectors.
  974.      *
  975.      * @param other Object to test for equality.
  976.      * @return {@code true} if two vector objects are equal, {@code false}
  977.      * otherwise.
  978.      */
  979.     @Override
  980.     public boolean equals(Object other) {
  981.         if (this == other) {
  982.             return true;
  983.         }
  984.         if (other == null) {
  985.             return false;
  986.         }

  987.         try {
  988.             @SuppressWarnings("unchecked") // May fail, but we ignore ClassCastException
  989.             FieldVector<T> rhs = (FieldVector<T>) other;
  990.             if (data.length != rhs.getDimension()) {
  991.                 return false;
  992.             }

  993.             for (int i = 0; i < data.length; ++i) {
  994.                 if (!data[i].equals(rhs.getEntry(i))) {
  995.                     return false;
  996.                 }
  997.             }
  998.             return true;
  999.         } catch (ClassCastException ex) {
  1000.             // ignore exception
  1001.             return false;
  1002.         }
  1003.     }

  1004.     /**
  1005.      * Get a hashCode for the real vector.
  1006.      * <p>All NaN values have the same hash code.</p>
  1007.      * @return a hash code value for this object
  1008.      */
  1009.     @Override
  1010.     public int hashCode() {
  1011.         int h = 3542;
  1012.         for (final T a : data) {
  1013.             h ^= a.hashCode();
  1014.         }
  1015.         return h;
  1016.     }

  1017.     /**
  1018.      * Check if an index is valid.
  1019.      *
  1020.      * @param index Index to check.
  1021.      * @exception MathIllegalArgumentException if the index is not valid.
  1022.      */
  1023.     private void checkIndex(final int index) throws MathIllegalArgumentException {
  1024.         if (index < 0 || index >= getDimension()) {
  1025.             throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX,
  1026.                                           index, 0, getDimension() - 1);
  1027.         }
  1028.     }

  1029.     /**
  1030.      * Checks that the indices of a subvector are valid.
  1031.      *
  1032.      * @param start the index of the first entry of the subvector
  1033.      * @param end the index of the last entry of the subvector (inclusive)
  1034.      * @throws MathIllegalArgumentException if {@code start} of {@code end} are not valid
  1035.      * @throws MathIllegalArgumentException if {@code end < start}
  1036.      */
  1037.     private void checkIndices(final int start, final int end)
  1038.         throws MathIllegalArgumentException {
  1039.         final int dim = getDimension();
  1040.         if ((start < 0) || (start >= dim)) {
  1041.             throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX, start, 0,
  1042.                                           dim - 1);
  1043.         }
  1044.         if ((end < 0) || (end >= dim)) {
  1045.             throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX, end, 0,
  1046.                                           dim - 1);
  1047.         }
  1048.         if (end < start) {
  1049.             throw new MathIllegalArgumentException(LocalizedCoreFormats.INITIAL_ROW_AFTER_FINAL_ROW,
  1050.                                                 end, start, false);
  1051.         }
  1052.     }

  1053. }