ArrayRealVector.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 java.util.Iterator;

  21. import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
  22. import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
  23. import org.apache.commons.math4.legacy.exception.NotPositiveException;
  24. import org.apache.commons.math4.legacy.exception.NullArgumentException;
  25. import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
  26. import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
  27. import org.apache.commons.math4.legacy.exception.OutOfRangeException;
  28. import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
  29. import org.apache.commons.math4.core.jdkmath.JdkMath;

  30. /**
  31.  * This class implements the {@link RealVector} interface with a double array.
  32.  * @since 2.0
  33.  */
  34. public class ArrayRealVector extends RealVector implements Serializable {
  35.     /** Serializable version identifier. */
  36.     private static final long serialVersionUID = -1097961340710804027L;
  37.     /** Default format. */
  38.     private static final RealVectorFormat DEFAULT_FORMAT = RealVectorFormat.getInstance();

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

  41.     /**
  42.      * Build a 0-length vector.
  43.      * Zero-length vectors may be used to initialized construction of vectors
  44.      * by data gathering. We start with zero-length and use either the {@link
  45.      * #ArrayRealVector(ArrayRealVector, ArrayRealVector)} constructor
  46.      * or one of the {@code append} method ({@link #append(double)},
  47.      * {@link #append(ArrayRealVector)}) to gather data into this vector.
  48.      */
  49.     public ArrayRealVector() {
  50.         data = new double[0];
  51.     }

  52.     /**
  53.      * Construct a vector of zeroes.
  54.      *
  55.      * @param size Size of the vector.
  56.      */
  57.     public ArrayRealVector(int size) {
  58.         data = new double[size];
  59.     }

  60.     /**
  61.      * Construct a vector with preset values.
  62.      *
  63.      * @param size Size of the vector
  64.      * @param preset All entries will be set with this value.
  65.      */
  66.     public ArrayRealVector(int size, double preset) {
  67.         data = new double[size];
  68.         Arrays.fill(data, preset);
  69.     }

  70.     /**
  71.      * Construct a vector from an array, copying the input array.
  72.      *
  73.      * @param d Array.
  74.      */
  75.     public ArrayRealVector(double[] d) {
  76.         data = d.clone();
  77.     }

  78.     /**
  79.      * Create a new ArrayRealVector using the input array as the underlying
  80.      * data array.
  81.      * If an array is built specially in order to be embedded in a
  82.      * ArrayRealVector and not used directly, the {@code copyArray} may be
  83.      * set to {@code false}. This will prevent the copying and improve
  84.      * performance as no new array will be built and no data will be copied.
  85.      *
  86.      * @param d Data for the new vector.
  87.      * @param copyArray if {@code true}, the input array will be copied,
  88.      * otherwise it will be referenced.
  89.      * @throws NullArgumentException if {@code d} is {@code null}.
  90.      * @see #ArrayRealVector(double[])
  91.      */
  92.     public ArrayRealVector(double[] d, boolean copyArray)
  93.         throws NullArgumentException {
  94.         if (d == null) {
  95.             throw new NullArgumentException();
  96.         }
  97.         data = copyArray ? d.clone() :  d;
  98.     }

  99.     /**
  100.      * Construct a vector from part of a array.
  101.      *
  102.      * @param d Array.
  103.      * @param pos Position of first entry.
  104.      * @param size Number of entries to copy.
  105.      * @throws NullArgumentException if {@code d} is {@code null}.
  106.      * @throws NumberIsTooLargeException if the size of {@code d} is less
  107.      * than {@code pos + size}.
  108.      */
  109.     public ArrayRealVector(double[] d, int pos, int size)
  110.         throws NullArgumentException, NumberIsTooLargeException {
  111.         if (d == null) {
  112.             throw new NullArgumentException();
  113.         }
  114.         if (d.length < pos + size) {
  115.             throw new NumberIsTooLargeException(pos + size, d.length, true);
  116.         }
  117.         data = new double[size];
  118.         System.arraycopy(d, pos, data, 0, size);
  119.     }

  120.     /**
  121.      * Construct a vector from an array.
  122.      *
  123.      * @param d Array of {@code Double}s.
  124.      */
  125.     public ArrayRealVector(Double[] d) {
  126.         data = new double[d.length];
  127.         for (int i = 0; i < d.length; i++) {
  128.             data[i] = d[i].doubleValue();
  129.         }
  130.     }

  131.     /**
  132.      * Construct a vector from part of an array.
  133.      *
  134.      * @param d Array.
  135.      * @param pos Position of first entry.
  136.      * @param size Number of entries to copy.
  137.      * @throws NullArgumentException if {@code d} is {@code null}.
  138.      * @throws NumberIsTooLargeException if the size of {@code d} is less
  139.      * than {@code pos + size}.
  140.      */
  141.     public ArrayRealVector(Double[] d, int pos, int size)
  142.         throws NullArgumentException, NumberIsTooLargeException {
  143.         if (d == null) {
  144.             throw new NullArgumentException();
  145.         }
  146.         if (d.length < pos + size) {
  147.             throw new NumberIsTooLargeException(pos + size, d.length, true);
  148.         }
  149.         data = new double[size];
  150.         for (int i = pos; i < pos + size; i++) {
  151.             data[i - pos] = d[i].doubleValue();
  152.         }
  153.     }

  154.     /**
  155.      * Construct a vector from another vector, using a deep copy.
  156.      *
  157.      * @param v vector to copy.
  158.      * @throws NullArgumentException if {@code v} is {@code null}.
  159.      */
  160.     public ArrayRealVector(RealVector v) throws NullArgumentException {
  161.         if (v == null) {
  162.             throw new NullArgumentException();
  163.         }
  164.         data = new double[v.getDimension()];
  165.         for (int i = 0; i < data.length; ++i) {
  166.             data[i] = v.getEntry(i);
  167.         }
  168.     }

  169.     /**
  170.      * Construct a vector from another vector, using a deep copy.
  171.      *
  172.      * @param v Vector to copy.
  173.      * @throws NullArgumentException if {@code v} is {@code null}.
  174.      */
  175.     public ArrayRealVector(ArrayRealVector v) throws NullArgumentException {
  176.         this(v, true);
  177.     }

  178.     /**
  179.      * Construct a vector from another vector.
  180.      *
  181.      * @param v Vector to copy.
  182.      * @param deep If {@code true} perform a deep copy, otherwise perform a
  183.      * shallow copy.
  184.      */
  185.     public ArrayRealVector(ArrayRealVector v, boolean deep) {
  186.         data = deep ? v.data.clone() : v.data;
  187.     }

  188.     /**
  189.      * Construct a vector by appending one vector to another vector.
  190.      * @param v1 First vector (will be put in front of the new vector).
  191.      * @param v2 Second vector (will be put at back of the new vector).
  192.      */
  193.     public ArrayRealVector(ArrayRealVector v1, ArrayRealVector v2) {
  194.         data = new double[v1.data.length + v2.data.length];
  195.         System.arraycopy(v1.data, 0, data, 0, v1.data.length);
  196.         System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length);
  197.     }

  198.     /**
  199.      * Construct a vector by appending one vector to another vector.
  200.      * @param v1 First vector (will be put in front of the new vector).
  201.      * @param v2 Second vector (will be put at back of the new vector).
  202.      */
  203.     public ArrayRealVector(ArrayRealVector v1, RealVector v2) {
  204.         final int l1 = v1.data.length;
  205.         final int l2 = v2.getDimension();
  206.         data = new double[l1 + l2];
  207.         System.arraycopy(v1.data, 0, data, 0, l1);
  208.         for (int i = 0; i < l2; ++i) {
  209.             data[l1 + i] = v2.getEntry(i);
  210.         }
  211.     }

  212.     /**
  213.      * Construct a vector by appending one vector to another vector.
  214.      * @param v1 First vector (will be put in front of the new vector).
  215.      * @param v2 Second vector (will be put at back of the new vector).
  216.      */
  217.     public ArrayRealVector(RealVector v1, ArrayRealVector v2) {
  218.         final int l1 = v1.getDimension();
  219.         final int l2 = v2.data.length;
  220.         data = new double[l1 + l2];
  221.         for (int i = 0; i < l1; ++i) {
  222.             data[i] = v1.getEntry(i);
  223.         }
  224.         System.arraycopy(v2.data, 0, data, l1, l2);
  225.     }

  226.     /**
  227.      * Construct a vector by appending one vector to another vector.
  228.      * @param v1 First vector (will be put in front of the new vector).
  229.      * @param v2 Second vector (will be put at back of the new vector).
  230.      */
  231.     public ArrayRealVector(ArrayRealVector v1, double[] v2) {
  232.         final int l1 = v1.getDimension();
  233.         final int l2 = v2.length;
  234.         data = new double[l1 + l2];
  235.         System.arraycopy(v1.data, 0, data, 0, l1);
  236.         System.arraycopy(v2, 0, data, l1, l2);
  237.     }

  238.     /**
  239.      * Construct a vector by appending one vector to another vector.
  240.      * @param v1 First vector (will be put in front of the new vector).
  241.      * @param v2 Second vector (will be put at back of the new vector).
  242.      */
  243.     public ArrayRealVector(double[] v1, ArrayRealVector v2) {
  244.         final int l1 = v1.length;
  245.         final int l2 = v2.getDimension();
  246.         data = new double[l1 + l2];
  247.         System.arraycopy(v1, 0, data, 0, l1);
  248.         System.arraycopy(v2.data, 0, data, l1, l2);
  249.     }

  250.     /**
  251.      * Construct a vector by appending one vector to another vector.
  252.      * @param v1 first vector (will be put in front of the new vector)
  253.      * @param v2 second vector (will be put at back of the new vector)
  254.      */
  255.     public ArrayRealVector(double[] v1, double[] v2) {
  256.         final int l1 = v1.length;
  257.         final int l2 = v2.length;
  258.         data = new double[l1 + l2];
  259.         System.arraycopy(v1, 0, data, 0, l1);
  260.         System.arraycopy(v2, 0, data, l1, l2);
  261.     }

  262.     /** {@inheritDoc} */
  263.     @Override
  264.     public ArrayRealVector copy() {
  265.         return new ArrayRealVector(this, true);
  266.     }

  267.     /** {@inheritDoc} */
  268.     @Override
  269.     public ArrayRealVector add(RealVector v)
  270.         throws DimensionMismatchException {
  271.         if (v instanceof ArrayRealVector) {
  272.             final double[] vData = ((ArrayRealVector) v).data;
  273.             final int dim = vData.length;
  274.             checkVectorDimensions(dim);
  275.             ArrayRealVector result = new ArrayRealVector(dim);
  276.             double[] resultData = result.data;
  277.             for (int i = 0; i < dim; i++) {
  278.                 resultData[i] = data[i] + vData[i];
  279.             }
  280.             return result;
  281.         } else {
  282.             checkVectorDimensions(v);
  283.             double[] out = data.clone();
  284.             Iterator<Entry> it = v.iterator();
  285.             while (it.hasNext()) {
  286.                 final Entry e = it.next();
  287.                 out[e.getIndex()] += e.getValue();
  288.             }
  289.             return new ArrayRealVector(out, false);
  290.         }
  291.     }

  292.     /** {@inheritDoc} */
  293.     @Override
  294.     public ArrayRealVector subtract(RealVector v)
  295.         throws DimensionMismatchException {
  296.         if (v instanceof ArrayRealVector) {
  297.             final double[] vData = ((ArrayRealVector) v).data;
  298.             final int dim = vData.length;
  299.             checkVectorDimensions(dim);
  300.             ArrayRealVector result = new ArrayRealVector(dim);
  301.             double[] resultData = result.data;
  302.             for (int i = 0; i < dim; i++) {
  303.                 resultData[i] = data[i] - vData[i];
  304.             }
  305.             return result;
  306.         } else {
  307.             checkVectorDimensions(v);
  308.             double[] out = data.clone();
  309.             Iterator<Entry> it = v.iterator();
  310.             while (it.hasNext()) {
  311.                 final Entry e = it.next();
  312.                 out[e.getIndex()] -= e.getValue();
  313.             }
  314.             return new ArrayRealVector(out, false);
  315.         }
  316.     }

  317.     /** {@inheritDoc} */
  318.     @Override
  319.     public ArrayRealVector map(UnivariateFunction function) {
  320.         return copy().mapToSelf(function);
  321.     }

  322.     /** {@inheritDoc} */
  323.     @Override
  324.     public ArrayRealVector mapToSelf(UnivariateFunction function) {
  325.         for (int i = 0; i < data.length; i++) {
  326.             data[i] = function.value(data[i]);
  327.         }
  328.         return this;
  329.     }

  330.     /** {@inheritDoc} */
  331.     @Override
  332.     public RealVector mapAddToSelf(double d) {
  333.         for (int i = 0; i < data.length; i++) {
  334.             data[i] += d;
  335.         }
  336.         return this;
  337.     }

  338.     /** {@inheritDoc} */
  339.     @Override
  340.     public RealVector mapSubtractToSelf(double d) {
  341.         for (int i = 0; i < data.length; i++) {
  342.             data[i] -= d;
  343.         }
  344.         return this;
  345.     }

  346.     /** {@inheritDoc} */
  347.     @Override
  348.     public RealVector mapMultiplyToSelf(double d) {
  349.         for (int i = 0; i < data.length; i++) {
  350.             data[i] *= d;
  351.         }
  352.         return this;
  353.     }

  354.     /** {@inheritDoc} */
  355.     @Override
  356.     public RealVector mapDivideToSelf(double d) {
  357.         for (int i = 0; i < data.length; i++) {
  358.             data[i] /= d;
  359.         }
  360.         return this;
  361.     }

  362.     /** {@inheritDoc} */
  363.     @Override
  364.     public ArrayRealVector ebeMultiply(RealVector v)
  365.         throws DimensionMismatchException {
  366.         if (v instanceof ArrayRealVector) {
  367.             final double[] vData = ((ArrayRealVector) v).data;
  368.             final int dim = vData.length;
  369.             checkVectorDimensions(dim);
  370.             ArrayRealVector result = new ArrayRealVector(dim);
  371.             double[] resultData = result.data;
  372.             for (int i = 0; i < dim; i++) {
  373.                 resultData[i] = data[i] * vData[i];
  374.             }
  375.             return result;
  376.         } else {
  377.             checkVectorDimensions(v);
  378.             double[] out = data.clone();
  379.             for (int i = 0; i < data.length; i++) {
  380.                 out[i] *= v.getEntry(i);
  381.             }
  382.             return new ArrayRealVector(out, false);
  383.         }
  384.     }

  385.     /** {@inheritDoc} */
  386.     @Override
  387.     public ArrayRealVector ebeDivide(RealVector v)
  388.         throws DimensionMismatchException {
  389.         if (v instanceof ArrayRealVector) {
  390.             final double[] vData = ((ArrayRealVector) v).data;
  391.             final int dim = vData.length;
  392.             checkVectorDimensions(dim);
  393.             ArrayRealVector result = new ArrayRealVector(dim);
  394.             double[] resultData = result.data;
  395.             for (int i = 0; i < dim; i++) {
  396.                 resultData[i] = data[i] / vData[i];
  397.             }
  398.             return result;
  399.         } else {
  400.             checkVectorDimensions(v);
  401.             double[] out = data.clone();
  402.             for (int i = 0; i < data.length; i++) {
  403.                 out[i] /= v.getEntry(i);
  404.             }
  405.             return new ArrayRealVector(out, false);
  406.         }
  407.     }

  408.     /**
  409.      * Get a reference to the underlying data array.
  410.      * This method does not make a fresh copy of the underlying data.
  411.      *
  412.      * @return the array of entries.
  413.      */
  414.     public double[] getDataRef() {
  415.         return data;
  416.     }

  417.     /** {@inheritDoc} */
  418.     @Override
  419.     public double dotProduct(RealVector v) throws DimensionMismatchException {
  420.         if (v instanceof ArrayRealVector) {
  421.             final double[] vData = ((ArrayRealVector) v).data;
  422.             checkVectorDimensions(vData.length);
  423.             double dot = 0;
  424.             for (int i = 0; i < data.length; i++) {
  425.                 dot += data[i] * vData[i];
  426.             }
  427.             return dot;
  428.         }
  429.         return super.dotProduct(v);
  430.     }

  431.     /** {@inheritDoc} */
  432.     @Override
  433.     public double getNorm() {
  434.         double sum = 0;
  435.         for (double a : data) {
  436.             sum += a * a;
  437.         }
  438.         return JdkMath.sqrt(sum);
  439.     }

  440.     /** {@inheritDoc} */
  441.     @Override
  442.     public double getL1Norm() {
  443.         double sum = 0;
  444.         for (double a : data) {
  445.             sum += JdkMath.abs(a);
  446.         }
  447.         return sum;
  448.     }

  449.     /** {@inheritDoc} */
  450.     @Override
  451.     public double getLInfNorm() {
  452.         double max = 0;
  453.         for (double a : data) {
  454.             max = JdkMath.max(max, JdkMath.abs(a));
  455.         }
  456.         return max;
  457.     }

  458.     /** {@inheritDoc} */
  459.     @Override
  460.     public double getDistance(RealVector v) throws DimensionMismatchException {
  461.         if (v instanceof ArrayRealVector) {
  462.             final double[] vData = ((ArrayRealVector) v).data;
  463.             checkVectorDimensions(vData.length);
  464.             double sum = 0;
  465.             for (int i = 0; i < data.length; ++i) {
  466.                 final double delta = data[i] - vData[i];
  467.                 sum += delta * delta;
  468.             }
  469.             return JdkMath.sqrt(sum);
  470.         } else {
  471.             checkVectorDimensions(v);
  472.             double sum = 0;
  473.             for (int i = 0; i < data.length; ++i) {
  474.                 final double delta = data[i] - v.getEntry(i);
  475.                 sum += delta * delta;
  476.             }
  477.             return JdkMath.sqrt(sum);
  478.         }
  479.     }

  480.     /** {@inheritDoc} */
  481.     @Override
  482.     public double getL1Distance(RealVector v)
  483.         throws DimensionMismatchException {
  484.         if (v instanceof ArrayRealVector) {
  485.             final double[] vData = ((ArrayRealVector) v).data;
  486.             checkVectorDimensions(vData.length);
  487.             double sum = 0;
  488.             for (int i = 0; i < data.length; ++i) {
  489.                 final double delta = data[i] - vData[i];
  490.                 sum += JdkMath.abs(delta);
  491.             }
  492.             return sum;
  493.         } else {
  494.             checkVectorDimensions(v);
  495.             double sum = 0;
  496.             for (int i = 0; i < data.length; ++i) {
  497.                 final double delta = data[i] - v.getEntry(i);
  498.                 sum += JdkMath.abs(delta);
  499.             }
  500.             return sum;
  501.         }
  502.     }

  503.     /** {@inheritDoc} */
  504.     @Override
  505.     public double getLInfDistance(RealVector v)
  506.         throws DimensionMismatchException {
  507.         if (v instanceof ArrayRealVector) {
  508.             final double[] vData = ((ArrayRealVector) v).data;
  509.             checkVectorDimensions(vData.length);
  510.             double max = 0;
  511.             for (int i = 0; i < data.length; ++i) {
  512.                 final double delta = data[i] - vData[i];
  513.                 max = JdkMath.max(max, JdkMath.abs(delta));
  514.             }
  515.             return max;
  516.         } else {
  517.             checkVectorDimensions(v);
  518.             double max = 0;
  519.             for (int i = 0; i < data.length; ++i) {
  520.                 final double delta = data[i] - v.getEntry(i);
  521.                 max = JdkMath.max(max, JdkMath.abs(delta));
  522.             }
  523.             return max;
  524.         }
  525.     }

  526.     /** {@inheritDoc} */
  527.     @Override
  528.     public RealMatrix outerProduct(RealVector v) {
  529.         if (v instanceof ArrayRealVector) {
  530.             final double[] vData = ((ArrayRealVector) v).data;
  531.             final int m = data.length;
  532.             final int n = vData.length;
  533.             final RealMatrix out = MatrixUtils.createRealMatrix(m, n);
  534.             for (int i = 0; i < m; i++) {
  535.                 for (int j = 0; j < n; j++) {
  536.                     out.setEntry(i, j, data[i] * vData[j]);
  537.                 }
  538.             }
  539.             return out;
  540.         } else {
  541.             final int m = data.length;
  542.             final int n = v.getDimension();
  543.             final RealMatrix out = MatrixUtils.createRealMatrix(m, n);
  544.             for (int i = 0; i < m; i++) {
  545.                 for (int j = 0; j < n; j++) {
  546.                     out.setEntry(i, j, data[i] * v.getEntry(j));
  547.                 }
  548.             }
  549.             return out;
  550.         }
  551.     }

  552.     /** {@inheritDoc} */
  553.     @Override
  554.     public double getEntry(int index) throws OutOfRangeException {
  555.         try {
  556.             return data[index];
  557.         } catch (IndexOutOfBoundsException e) {
  558.             throw new OutOfRangeException(LocalizedFormats.INDEX, index, 0,
  559.                 getDimension() - 1);
  560.         }
  561.     }

  562.     /** {@inheritDoc} */
  563.     @Override
  564.     public int getDimension() {
  565.         return data.length;
  566.     }

  567.     /** {@inheritDoc} */
  568.     @Override
  569.     public RealVector append(RealVector v) {
  570.         if (v instanceof ArrayRealVector) {
  571.             return new ArrayRealVector(this, (ArrayRealVector) v);
  572.         }
  573.         return new ArrayRealVector(this, v);
  574.     }

  575.     /**
  576.      * Construct a vector by appending a vector to this vector.
  577.      *
  578.      * @param v Vector to append to this one.
  579.      * @return a new vector.
  580.      */
  581.     public ArrayRealVector append(ArrayRealVector v) {
  582.         return new ArrayRealVector(this, v);
  583.     }

  584.     /** {@inheritDoc} */
  585.     @Override
  586.     public RealVector append(double in) {
  587.         final double[] out = new double[data.length + 1];
  588.         System.arraycopy(data, 0, out, 0, data.length);
  589.         out[data.length] = in;
  590.         return new ArrayRealVector(out, false);
  591.     }

  592.     /** {@inheritDoc} */
  593.     @Override
  594.     public RealVector getSubVector(int index, int n)
  595.         throws OutOfRangeException, NotPositiveException {
  596.         if (n < 0) {
  597.             throw new NotPositiveException(LocalizedFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
  598.         }
  599.         ArrayRealVector out = new ArrayRealVector(n);
  600.         try {
  601.             System.arraycopy(data, index, out.data, 0, n);
  602.         } catch (IndexOutOfBoundsException e) {
  603.             checkIndex(index);
  604.             checkIndex(index + n - 1);
  605.         }
  606.         return out;
  607.     }

  608.     /** {@inheritDoc} */
  609.     @Override
  610.     public void setEntry(int index, double value) throws OutOfRangeException {
  611.         try {
  612.             data[index] = value;
  613.         } catch (IndexOutOfBoundsException e) {
  614.             checkIndex(index);
  615.         }
  616.     }

  617.     /** {@inheritDoc} */
  618.     @Override
  619.     public void addToEntry(int index, double increment)
  620.         throws OutOfRangeException {
  621.         try {
  622.         data[index] += increment;
  623.         } catch(IndexOutOfBoundsException e){
  624.             throw new OutOfRangeException(LocalizedFormats.INDEX,
  625.                                           index, 0, data.length - 1);
  626.         }
  627.     }

  628.     /** {@inheritDoc} */
  629.     @Override
  630.     public void setSubVector(int index, RealVector v)
  631.         throws OutOfRangeException {
  632.         if (v instanceof ArrayRealVector) {
  633.             setSubVector(index, ((ArrayRealVector) v).data);
  634.         } else {
  635.             try {
  636.                 for (int i = index; i < index + v.getDimension(); ++i) {
  637.                     data[i] = v.getEntry(i - index);
  638.                 }
  639.             } catch (IndexOutOfBoundsException e) {
  640.                 checkIndex(index);
  641.                 checkIndex(index + v.getDimension() - 1);
  642.             }
  643.         }
  644.     }

  645.     /**
  646.      * Set a set of consecutive elements.
  647.      *
  648.      * @param index Index of first element to be set.
  649.      * @param v Vector containing the values to set.
  650.      * @throws OutOfRangeException if the index is inconsistent with the vector
  651.      * size.
  652.      */
  653.     public void setSubVector(int index, double[] v)
  654.         throws OutOfRangeException {
  655.         try {
  656.             System.arraycopy(v, 0, data, index, v.length);
  657.         } catch (IndexOutOfBoundsException e) {
  658.             checkIndex(index);
  659.             checkIndex(index + v.length - 1);
  660.         }
  661.     }

  662.     /** {@inheritDoc} */
  663.     @Override
  664.     public void set(double value) {
  665.         Arrays.fill(data, value);
  666.     }

  667.     /** {@inheritDoc} */
  668.     @Override
  669.     public double[] toArray(){
  670.         return data.clone();
  671.     }

  672.     /** {@inheritDoc} */
  673.     @Override
  674.     public String toString(){
  675.         return DEFAULT_FORMAT.format(this);
  676.     }

  677.     /**
  678.      * Check if instance and specified vectors have the same dimension.
  679.      *
  680.      * @param v Vector to compare instance with.
  681.      * @throws DimensionMismatchException if the vectors do not
  682.      * have the same dimension.
  683.      */
  684.     @Override
  685.     protected void checkVectorDimensions(RealVector v)
  686.         throws DimensionMismatchException {
  687.         checkVectorDimensions(v.getDimension());
  688.     }

  689.     /**
  690.      * Check if instance dimension is equal to some expected value.
  691.      *
  692.      * @param n Expected dimension.
  693.      * @throws DimensionMismatchException if the dimension is
  694.      * inconsistent with vector size.
  695.      */
  696.     @Override
  697.     protected void checkVectorDimensions(int n)
  698.         throws DimensionMismatchException {
  699.         if (data.length != n) {
  700.             throw new DimensionMismatchException(data.length, n);
  701.         }
  702.     }

  703.     /**
  704.      * Check if any coordinate of this vector is {@code NaN}.
  705.      *
  706.      * @return {@code true} if any coordinate of this vector is {@code NaN},
  707.      * {@code false} otherwise.
  708.      */
  709.     @Override
  710.     public boolean isNaN() {
  711.         for (double v : data) {
  712.             if (Double.isNaN(v)) {
  713.                 return true;
  714.             }
  715.         }
  716.         return false;
  717.     }

  718.     /**
  719.      * Check whether any coordinate of this vector is infinite and none
  720.      * are {@code NaN}.
  721.      *
  722.      * @return {@code true} if any coordinate of this vector is infinite and
  723.      * none are {@code NaN}, {@code false} otherwise.
  724.      */
  725.     @Override
  726.     public boolean isInfinite() {
  727.         if (isNaN()) {
  728.             return false;
  729.         }

  730.         for (double v : data) {
  731.             if (Double.isInfinite(v)) {
  732.                 return true;
  733.             }
  734.         }

  735.         return false;
  736.     }

  737.     /** {@inheritDoc} */
  738.     @Override
  739.     public boolean equals(Object other) {
  740.         if (this == other) {
  741.             return true;
  742.         }

  743.         if (!(other instanceof RealVector)) {
  744.             return false;
  745.         }

  746.         RealVector rhs = (RealVector) other;
  747.         if (data.length != rhs.getDimension()) {
  748.             return false;
  749.         }

  750.         if (rhs.isNaN()) {
  751.             return this.isNaN();
  752.         }

  753.         for (int i = 0; i < data.length; ++i) {
  754.             if (data[i] != rhs.getEntry(i)) {
  755.                 return false;
  756.             }
  757.         }
  758.         return true;
  759.     }

  760.     /**
  761.      * {@inheritDoc} All {@code NaN} values have the same hash code.
  762.      */
  763.     @Override
  764.     public int hashCode() {
  765.         if (isNaN()) {
  766.             return 9;
  767.         }
  768.         return Arrays.hashCode(data);
  769.     }

  770.     /** {@inheritDoc} */
  771.     @Override
  772.     public ArrayRealVector combine(double a, double b, RealVector y)
  773.         throws DimensionMismatchException {
  774.         return copy().combineToSelf(a, b, y);
  775.     }

  776.     /** {@inheritDoc} */
  777.     @Override
  778.     public ArrayRealVector combineToSelf(double a, double b, RealVector y)
  779.         throws DimensionMismatchException {
  780.         if (y instanceof ArrayRealVector) {
  781.             final double[] yData = ((ArrayRealVector) y).data;
  782.             checkVectorDimensions(yData.length);
  783.             for (int i = 0; i < this.data.length; i++) {
  784.                 data[i] = a * data[i] + b * yData[i];
  785.             }
  786.         } else {
  787.             checkVectorDimensions(y);
  788.             for (int i = 0; i < this.data.length; i++) {
  789.                 data[i] = a * data[i] + b * y.getEntry(i);
  790.             }
  791.         }
  792.         return this;
  793.     }

  794.     /** {@inheritDoc} */
  795.     @Override
  796.     public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor) {
  797.         visitor.start(data.length, 0, data.length - 1);
  798.         for (int i = 0; i < data.length; i++) {
  799.             visitor.visit(i, data[i]);
  800.         }
  801.         return visitor.end();
  802.     }

  803.     /** {@inheritDoc} */
  804.     @Override
  805.     public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor,
  806.         final int start, final int end) throws NumberIsTooSmallException,
  807.         OutOfRangeException {
  808.         checkIndices(start, end);
  809.         visitor.start(data.length, start, end);
  810.         for (int i = start; i <= end; i++) {
  811.             visitor.visit(i, data[i]);
  812.         }
  813.         return visitor.end();
  814.     }

  815.     /**
  816.      * {@inheritDoc}
  817.      *
  818.      * In this implementation, the optimized order is the default order.
  819.      */
  820.     @Override
  821.     public double walkInOptimizedOrder(final RealVectorPreservingVisitor visitor) {
  822.         return walkInDefaultOrder(visitor);
  823.     }

  824.     /**
  825.      * {@inheritDoc}
  826.      *
  827.      * In this implementation, the optimized order is the default order.
  828.      */
  829.     @Override
  830.     public double walkInOptimizedOrder(final RealVectorPreservingVisitor visitor,
  831.         final int start, final int end) throws NumberIsTooSmallException,
  832.         OutOfRangeException {
  833.         return walkInDefaultOrder(visitor, start, end);
  834.     }

  835.     /** {@inheritDoc} */
  836.     @Override
  837.     public double walkInDefaultOrder(final RealVectorChangingVisitor visitor) {
  838.         visitor.start(data.length, 0, data.length - 1);
  839.         for (int i = 0; i < data.length; i++) {
  840.             data[i] = visitor.visit(i, data[i]);
  841.         }
  842.         return visitor.end();
  843.     }

  844.     /** {@inheritDoc} */
  845.     @Override
  846.     public double walkInDefaultOrder(final RealVectorChangingVisitor visitor,
  847.         final int start, final int end) throws NumberIsTooSmallException,
  848.         OutOfRangeException {
  849.         checkIndices(start, end);
  850.         visitor.start(data.length, start, end);
  851.         for (int i = start; i <= end; i++) {
  852.             data[i] = visitor.visit(i, data[i]);
  853.         }
  854.         return visitor.end();
  855.     }

  856.     /**
  857.      * {@inheritDoc}
  858.      *
  859.      * In this implementation, the optimized order is the default order.
  860.      */
  861.     @Override
  862.     public double walkInOptimizedOrder(final RealVectorChangingVisitor visitor) {
  863.         return walkInDefaultOrder(visitor);
  864.     }

  865.     /**
  866.      * {@inheritDoc}
  867.      *
  868.      * In this implementation, the optimized order is the default order.
  869.      */
  870.     @Override
  871.     public double walkInOptimizedOrder(final RealVectorChangingVisitor visitor,
  872.         final int start, final int end) throws NumberIsTooSmallException,
  873.         OutOfRangeException {
  874.         return walkInDefaultOrder(visitor, start, end);
  875.     }
  876. }