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.  *      http://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.apache.commons.math4.legacy.linear;

  18. import java.io.Serializable;
  19. import java.util.Arrays;

  20. import org.apache.commons.math4.legacy.core.Field;
  21. import org.apache.commons.math4.legacy.core.FieldElement;
  22. import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
  23. import org.apache.commons.math4.legacy.exception.MathArithmeticException;
  24. import org.apache.commons.math4.legacy.exception.NotPositiveException;
  25. import org.apache.commons.math4.legacy.exception.NullArgumentException;
  26. import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
  27. import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
  28. import org.apache.commons.math4.legacy.exception.OutOfRangeException;
  29. import org.apache.commons.math4.legacy.exception.ZeroException;
  30. import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
  31. import org.apache.commons.math4.legacy.core.MathArrays;

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

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

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

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

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

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

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

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

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

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

  164.     /**
  165.      * Construct a vector from part of a array.
  166.      *
  167.      * @param d Array.
  168.      * @param pos Position of the first entry.
  169.      * @param size Number of entries to copy.
  170.      * @throws NullArgumentException if {@code d} is {@code null}.
  171.      * @throws NumberIsTooLargeException if the size of {@code d} is less
  172.      * than {@code pos + size}.
  173.      */
  174.     public ArrayFieldVector(T[] d, int pos, int size)
  175.             throws NullArgumentException, NumberIsTooLargeException {
  176.         NullArgumentException.check(d);
  177.         if (d.length < pos + size) {
  178.             throw new NumberIsTooLargeException(pos + size, d.length, true);
  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 NumberIsTooLargeException 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 NullArgumentException, NumberIsTooLargeException {
  197.         NullArgumentException.check(d);
  198.         if (d.length < pos + size) {
  199.             throw new NumberIsTooLargeException(pos + size, d.length, true);
  200.         }
  201.         this.field = field;
  202.         data = MathArrays.buildArray(field, size);
  203.         System.arraycopy(d, pos, data, 0, size);
  204.     }

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

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

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

  246.     /**
  247.      * Construct a vector by appending one vector to another vector.
  248.      *
  249.      * @param v1 First vector (will be put in front of the new vector).
  250.      * @param v2 Second vector (will be put at back of the new vector).
  251.      * @throws NullArgumentException if {@code v1} or {@code v2} is
  252.      * {@code null}.
  253.      * @since 3.2
  254.      */
  255.     public ArrayFieldVector(FieldVector<T> v1, FieldVector<T> v2)
  256.             throws NullArgumentException {
  257.         NullArgumentException.check(v1);
  258.         NullArgumentException.check(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.      * @since 3.2
  276.      */
  277.     public ArrayFieldVector(FieldVector<T> v1, T[] v2)
  278.             throws NullArgumentException {
  279.         NullArgumentException.check(v1);
  280.         NullArgumentException.check(v2);
  281.         field = v1.getField();
  282.         final T[] v1Data =
  283.                 (v1 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v1).data : v1.toArray();
  284.         data = MathArrays.buildArray(field, v1Data.length + v2.length);
  285.         System.arraycopy(v1Data, 0, data, 0, v1Data.length);
  286.         System.arraycopy(v2, 0, data, v1Data.length, v2.length);
  287.     }

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

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

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

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

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

  368.     /** {@inheritDoc} */
  369.     @Override
  370.     public FieldVector<T> add(FieldVector<T> v)
  371.         throws DimensionMismatchException {
  372.         if (v instanceof ArrayFieldVector) {
  373.             return add((ArrayFieldVector<T>) v);
  374.         }

  375.         checkVectorDimensions(v);
  376.         T[] out = MathArrays.buildArray(field, data.length);
  377.         for (int i = 0; i < data.length; i++) {
  378.             out[i] = data[i].add(v.getEntry(i));
  379.         }
  380.         return new ArrayFieldVector<>(field, out, false);
  381.     }

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

  398.     /** {@inheritDoc} */
  399.     @Override
  400.     public FieldVector<T> subtract(FieldVector<T> v)
  401.         throws DimensionMismatchException {
  402.         if (v instanceof ArrayFieldVector) {
  403.             return subtract((ArrayFieldVector<T>) v);
  404.         }

  405.         checkVectorDimensions(v);
  406.         T[] out = MathArrays.buildArray(field, data.length);
  407.         for (int i = 0; i < data.length; i++) {
  408.             out[i] = data[i].subtract(v.getEntry(i));
  409.         }
  410.         return new ArrayFieldVector<>(field, out, false);
  411.     }

  412.     /**
  413.      * Compute {@code this} minus {@code v}.
  414.      * @param v vector to be subtracted
  415.      * @return {@code this - v}
  416.      * @throws DimensionMismatchException if {@code v} is not the same size as
  417.      * {@code this}
  418.      */
  419.     public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v)
  420.         throws DimensionMismatchException {
  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, MathArithmeticException {
  483.         NullArgumentException.check(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, MathArithmeticException {
  494.         NullArgumentException.check(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 MathArithmeticException {
  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 MathArithmeticException e) {
  509.                 throw new MathArithmeticException(LocalizedFormats.INDEX, i);
  510.             }
  511.         }
  512.         return new ArrayFieldVector<>(field, out, false);
  513.     }

  514.     /** {@inheritDoc} */
  515.     @Override
  516.     public FieldVector<T> mapInvToSelf() throws MathArithmeticException {
  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 MathArithmeticException e) {
  522.                 throw new MathArithmeticException(LocalizedFormats.INDEX, i);
  523.             }
  524.         }
  525.         return this;
  526.     }

  527.     /** {@inheritDoc} */
  528.     @Override
  529.     public FieldVector<T> ebeMultiply(FieldVector<T> v)
  530.         throws DimensionMismatchException {
  531.         if (v instanceof ArrayFieldVector) {
  532.             return ebeMultiply((ArrayFieldVector<T>) v);
  533.         }

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

  557.     /** {@inheritDoc} */
  558.     @Override
  559.     public FieldVector<T> ebeDivide(FieldVector<T> v)
  560.         throws DimensionMismatchException, MathArithmeticException {
  561.         if (v instanceof ArrayFieldVector) {
  562.             return ebeDivide((ArrayFieldVector<T>) v);
  563.         }

  564.         checkVectorDimensions(v);
  565.         T[] out = MathArrays.buildArray(field, data.length);
  566.         for (int i = 0; i < data.length; i++) {
  567.             try {
  568.                 out[i] = data[i].divide(v.getEntry(i));
  569.             } catch (final MathArithmeticException e) {
  570.                 throw new MathArithmeticException(LocalizedFormats.INDEX, i);
  571.             }
  572.         }
  573.         return new ArrayFieldVector<>(field, out, false);
  574.     }

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

  596.     /**
  597.      * Returns a reference to the underlying data array.
  598.      * <p>Does not make a fresh copy of the underlying data.</p>
  599.      * @return array of entries
  600.      */
  601.     public T[] getDataRef() {
  602.         return data;
  603.     }

  604.     /** {@inheritDoc} */
  605.     @Override
  606.     public T dotProduct(FieldVector<T> v)
  607.         throws DimensionMismatchException {
  608.         if (v instanceof ArrayFieldVector) {
  609.             return dotProduct((ArrayFieldVector<T>) v);
  610.         }

  611.         checkVectorDimensions(v);
  612.         T dot = field.getZero();
  613.         for (int i = 0; i < data.length; i++) {
  614.             dot = dot.add(data[i].multiply(v.getEntry(i)));
  615.         }
  616.         return dot;
  617.     }

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

  634.     /** {@inheritDoc} */
  635.     @Override
  636.     public FieldVector<T> projection(FieldVector<T> v)
  637.         throws DimensionMismatchException, MathArithmeticException {
  638.         return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
  639.     }

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

  651.     /** {@inheritDoc} */
  652.     @Override
  653.     public FieldMatrix<T> outerProduct(FieldVector<T> v) {
  654.         if (v instanceof ArrayFieldVector) {
  655.             return outerProduct((ArrayFieldVector<T>) v);
  656.         }

  657.         final int m = data.length;
  658.         final int n = v.getDimension();
  659.         final FieldMatrix<T> out = new Array2DRowFieldMatrix<>(field, m, n);
  660.         for (int i = 0; i < m; i++) {
  661.             for (int j = 0; j < n; j++) {
  662.                 out.setEntry(i, j, data[i].multiply(v.getEntry(j)));
  663.             }
  664.         }
  665.         return out;
  666.     }

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

  683.     /** {@inheritDoc} */
  684.     @Override
  685.     public T getEntry(int index) {
  686.         return data[index];
  687.     }

  688.     /** {@inheritDoc} */
  689.     @Override
  690.     public int getDimension() {
  691.         return data.length;
  692.     }

  693.     /** {@inheritDoc} */
  694.     @Override
  695.     public FieldVector<T> append(FieldVector<T> v) {
  696.         if (v instanceof ArrayFieldVector) {
  697.             return append((ArrayFieldVector<T>) v);
  698.         }

  699.         return new ArrayFieldVector<>(this,new ArrayFieldVector<>(v));
  700.     }

  701.     /**
  702.      * Construct a vector by appending a vector to this vector.
  703.      * @param v vector to append to this one.
  704.      * @return a new vector
  705.      */
  706.     public ArrayFieldVector<T> append(ArrayFieldVector<T> v) {
  707.         return new ArrayFieldVector<>(this, v);
  708.     }

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

  717.     /** {@inheritDoc} */
  718.     @Override
  719.     public FieldVector<T> getSubVector(int index, int n)
  720.         throws OutOfRangeException, NotPositiveException {
  721.         if (n < 0) {
  722.             throw new NotPositiveException(LocalizedFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
  723.         }
  724.         ArrayFieldVector<T> out = new ArrayFieldVector<>(field, n);
  725.         try {
  726.             System.arraycopy(data, index, out.data, 0, n);
  727.         } catch (IndexOutOfBoundsException e) {
  728.             checkIndex(index);
  729.             checkIndex(index + n - 1);
  730.         }
  731.         return out;
  732.     }

  733.     /** {@inheritDoc} */
  734.     @Override
  735.     public void setEntry(int index, T value) {
  736.         try {
  737.             data[index] = value;
  738.         } catch (IndexOutOfBoundsException e) {
  739.             checkIndex(index);
  740.         }
  741.     }

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

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

  773.     /** {@inheritDoc} */
  774.     @Override
  775.     public void set(T value) {
  776.         Arrays.fill(data, value);
  777.     }

  778.     /** {@inheritDoc} */
  779.     @Override
  780.     public T[] toArray(){
  781.         return data.clone();
  782.     }

  783.     /**
  784.      * Check if instance and specified vectors have the same dimension.
  785.      * @param v vector to compare instance with
  786.      * @exception DimensionMismatchException if the vectors do not
  787.      * have the same dimensions
  788.      */
  789.     protected void checkVectorDimensions(FieldVector<T> v)
  790.         throws DimensionMismatchException {
  791.         checkVectorDimensions(v.getDimension());
  792.     }

  793.     /**
  794.      * Check if instance dimension is equal to some expected value.
  795.      *
  796.      * @param n Expected dimension.
  797.      * @throws DimensionMismatchException if the dimension is not equal to the
  798.      * size of {@code this} vector.
  799.      */
  800.     protected void checkVectorDimensions(int n)
  801.         throws DimensionMismatchException {
  802.         if (data.length != n) {
  803.             throw new DimensionMismatchException(data.length, n);
  804.         }
  805.     }

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

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

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

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

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

  900.     /**
  901.      * Visits (and possibly alters) some entries of this vector in default order
  902.      * (increasing index).
  903.      *
  904.      * @param visitor visitor to be used to process the entries of this vector
  905.      * @param start the index of the first entry to be visited
  906.      * @param end the index of the last entry to be visited (inclusive)
  907.      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
  908.      * at the end of the walk
  909.      * @throws NumberIsTooSmallException if {@code end < start}.
  910.      * @throws OutOfRangeException if the indices are not valid.
  911.      * @since 3.3
  912.      */
  913.     public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor,
  914.                                 final int start, final int end)
  915.         throws NumberIsTooSmallException, OutOfRangeException {
  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.      * @since 3.3
  934.      */
  935.     public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor) {
  936.         return walkInDefaultOrder(visitor);
  937.     }

  938.     /**
  939.      * Visits (and possibly change) some entries of this vector in optimized
  940.      * order. The order in which the entries are visited is selected so as to
  941.      * lead to the most efficient implementation; it might depend on the
  942.      * concrete implementation of this abstract class.
  943.      *
  944.      * @param visitor visitor to be used to process the entries of this vector
  945.      * @param start the index of the first entry to be visited
  946.      * @param end the index of the last entry to be visited (inclusive)
  947.      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
  948.      * at the end of the walk
  949.      * @throws NumberIsTooSmallException if {@code end < start}.
  950.      * @throws OutOfRangeException if the indices are not valid.
  951.      * @since 3.3
  952.      */
  953.     public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor,
  954.                                   final int start, final int end)
  955.         throws NumberIsTooSmallException, OutOfRangeException {
  956.         return walkInDefaultOrder(visitor, start, end);
  957.     }

  958.     /**
  959.      * Test for the equality of two vectors.
  960.      *
  961.      * @param other Object to test for equality.
  962.      * @return {@code true} if two vector objects are equal, {@code false}
  963.      * otherwise.
  964.      */
  965.     @Override
  966.     public boolean equals(Object other) {
  967.         if (this == other) {
  968.             return true;
  969.         }
  970.         if (other == null) {
  971.             return false;
  972.         }

  973.         if (!(other instanceof FieldVector)) {
  974.             return false;
  975.         }

  976.         FieldVector rhs = (FieldVector) other;
  977.         if (data.length != rhs.getDimension()) {
  978.             return false;
  979.         }

  980.         for (int i = 0; i < data.length; ++i) {
  981.             if (!data[i].equals(rhs.getEntry(i))) {
  982.                 return false;
  983.             }
  984.         }
  985.         return true;
  986.     }

  987.     /**
  988.      * Get a hashCode for the real vector.
  989.      * <p>All NaN values have the same hash code.</p>
  990.      * @return a hash code value for this object
  991.      */
  992.     @Override
  993.     public int hashCode() {
  994.         int h = 3542;
  995.         for (final T a : data) {
  996.             h ^= a.hashCode();
  997.         }
  998.         return h;
  999.     }

  1000.     /**
  1001.      * Check if an index is valid.
  1002.      *
  1003.      * @param index Index to check.
  1004.      * @exception OutOfRangeException if the index is not valid.
  1005.      */
  1006.     private void checkIndex(final int index) throws OutOfRangeException {
  1007.         if (index < 0 || index >= getDimension()) {
  1008.             throw new OutOfRangeException(LocalizedFormats.INDEX,
  1009.                                           index, 0, getDimension() - 1);
  1010.         }
  1011.     }

  1012.     /**
  1013.      * Checks that the indices of a subvector are valid.
  1014.      *
  1015.      * @param start the index of the first entry of the subvector
  1016.      * @param end the index of the last entry of the subvector (inclusive)
  1017.      * @throws OutOfRangeException if {@code start} of {@code end} are not valid
  1018.      * @throws NumberIsTooSmallException if {@code end < start}
  1019.      * @since 3.3
  1020.      */
  1021.     private void checkIndices(final int start, final int end)
  1022.         throws NumberIsTooSmallException, OutOfRangeException {
  1023.         final int dim = getDimension();
  1024.         if (start < 0 || start >= dim) {
  1025.             throw new OutOfRangeException(LocalizedFormats.INDEX, start, 0,
  1026.                                           dim - 1);
  1027.         }
  1028.         if (end < 0 || end >= dim) {
  1029.             throw new OutOfRangeException(LocalizedFormats.INDEX, end, 0,
  1030.                                           dim - 1);
  1031.         }
  1032.         if (end < start) {
  1033.             throw new NumberIsTooSmallException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW,
  1034.                                                 end, start, false);
  1035.         }
  1036.     }
  1037. }