RealVector.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /*
- * This is not the original file distributed by the Apache Software Foundation
- * It has been modified by the Hipparchus project
- */
- package org.hipparchus.linear;
- import java.util.Iterator;
- import java.util.NoSuchElementException;
- import org.hipparchus.analysis.FunctionUtils;
- import org.hipparchus.analysis.UnivariateFunction;
- import org.hipparchus.analysis.function.Add;
- import org.hipparchus.analysis.function.Divide;
- import org.hipparchus.analysis.function.Multiply;
- import org.hipparchus.exception.LocalizedCoreFormats;
- import org.hipparchus.exception.MathIllegalArgumentException;
- import org.hipparchus.exception.MathRuntimeException;
- import org.hipparchus.util.FastMath;
- /**
- * Class defining a real-valued vector with basic algebraic operations.
- * <p>
- * vector element indexing is 0-based -- e.g., {@code getEntry(0)}
- * returns the first element of the vector.
- * </p>
- * <p>
- * The {@code code map} and {@code mapToSelf} methods operate
- * on vectors element-wise, i.e. they perform the same operation (adding a scalar,
- * applying a function ...) on each element in turn. The {@code map}
- * versions create a new vector to hold the result and do not change the instance.
- * The {@code mapToSelf} version uses the instance itself to store the
- * results, so the instance is changed by this method. In all cases, the result
- * vector is returned by the methods, allowing the <i>fluent API</i>
- * style, like this:
- * </p>
- * <pre>
- * RealVector result = v.mapAddToSelf(3.4).mapToSelf(new Tan()).mapToSelf(new Power(2.3));
- * </pre>
- *
- */
- public abstract class RealVector {
- /** Empty constructor.
- * <p>
- * This constructor is not strictly necessary, but it prevents spurious
- * javadoc warnings with JDK 18 and later.
- * </p>
- * @since 3.0
- */
- protected RealVector() { // NOPMD - unnecessary constructor added intentionally to make javadoc happy
- // nothing to do
- }
- /**
- * Returns the size of the vector.
- *
- * @return the size of this vector.
- */
- public abstract int getDimension();
- /**
- * Return the entry at the specified index.
- *
- * @param index Index location of entry to be fetched.
- * @return the vector entry at {@code index}.
- * @throws MathIllegalArgumentException if the index is not valid.
- * @see #setEntry(int, double)
- */
- public abstract double getEntry(int index) throws MathIllegalArgumentException;
- /**
- * Set a single element.
- *
- * @param index element index.
- * @param value new value for the element.
- * @throws MathIllegalArgumentException if the index is not valid.
- * @see #getEntry(int)
- */
- public abstract void setEntry(int index, double value)
- throws MathIllegalArgumentException;
- /**
- * Change an entry at the specified index.
- *
- * @param index Index location of entry to be set.
- * @param increment Value to add to the vector entry.
- * @throws MathIllegalArgumentException if the index is not valid.
- */
- public void addToEntry(int index, double increment)
- throws MathIllegalArgumentException {
- setEntry(index, getEntry(index) + increment);
- }
- /**
- * Construct a new vector by appending a vector to this vector.
- *
- * @param v vector to append to this one.
- * @return a new vector.
- */
- public abstract RealVector append(RealVector v);
- /**
- * Construct a new vector by appending a double to this vector.
- *
- * @param d double to append.
- * @return a new vector.
- */
- public abstract RealVector append(double d);
- /**
- * Get a subvector from consecutive elements.
- *
- * @param index index of first element.
- * @param n number of elements to be retrieved.
- * @return a vector containing n elements.
- * @throws MathIllegalArgumentException if the index is not valid.
- * @throws MathIllegalArgumentException if the number of elements is not positive.
- */
- public abstract RealVector getSubVector(int index, int n)
- throws MathIllegalArgumentException;
- /**
- * Set a sequence of consecutive elements.
- *
- * @param index index of first element to be set.
- * @param v vector containing the values to set.
- * @throws MathIllegalArgumentException if the index is not valid.
- */
- public abstract void setSubVector(int index, RealVector v)
- throws MathIllegalArgumentException;
- /**
- * Check whether any coordinate of this vector is {@code NaN}.
- *
- * @return {@code true} if any coordinate of this vector is {@code NaN},
- * {@code false} otherwise.
- */
- public abstract boolean isNaN();
- /**
- * Check whether any coordinate of this vector is infinite and none are {@code NaN}.
- *
- * @return {@code true} if any coordinate of this vector is infinite and
- * none are {@code NaN}, {@code false} otherwise.
- */
- public abstract boolean isInfinite();
- /**
- * Check if instance and specified vectors have the same dimension.
- *
- * @param v Vector to compare instance with.
- * @throws MathIllegalArgumentException if the vectors do not
- * have the same dimension.
- */
- protected void checkVectorDimensions(RealVector v)
- throws MathIllegalArgumentException {
- checkVectorDimensions(v.getDimension());
- }
- /**
- * Check if instance dimension is equal to some expected value.
- *
- * @param n Expected dimension.
- * @throws MathIllegalArgumentException if the dimension is
- * inconsistent with the vector size.
- */
- protected void checkVectorDimensions(int n)
- throws MathIllegalArgumentException {
- int d = getDimension();
- if (d != n) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
- d, n);
- }
- }
- /**
- * Check if an index is valid.
- *
- * @param index Index to check.
- * @exception MathIllegalArgumentException if {@code index} is not valid.
- */
- protected void checkIndex(final int index) throws MathIllegalArgumentException {
- if (index < 0 ||
- index >= getDimension()) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX,
- index, 0, getDimension() - 1);
- }
- }
- /**
- * Checks that the indices of a subvector are valid.
- *
- * @param start the index of the first entry of the subvector
- * @param end the index of the last entry of the subvector (inclusive)
- * @throws MathIllegalArgumentException if {@code start} of {@code end} are not valid
- * @throws MathIllegalArgumentException if {@code end < start}
- */
- protected void checkIndices(final int start, final int end)
- throws MathIllegalArgumentException {
- final int dim = getDimension();
- if ((start < 0) || (start >= dim)) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX, start, 0,
- dim - 1);
- }
- if ((end < 0) || (end >= dim)) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX, end, 0,
- dim - 1);
- }
- if (end < start) {
- // TODO Use more specific error message
- throw new MathIllegalArgumentException(LocalizedCoreFormats.INITIAL_ROW_AFTER_FINAL_ROW,
- end, start, false);
- }
- }
- /**
- * Compute the sum of this vector and {@code v}.
- * Returns a new vector. Does not change instance data.
- *
- * @param v Vector to be added.
- * @return {@code this} + {@code v}.
- * @throws MathIllegalArgumentException if {@code v} is not the same size as
- * {@code this} vector.
- */
- public RealVector add(RealVector v) throws MathIllegalArgumentException {
- checkVectorDimensions(v);
- RealVector result = v.copy();
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- final int index = e.getIndex();
- result.setEntry(index, e.getValue() + result.getEntry(index));
- }
- return result;
- }
- /**
- * Subtract {@code v} from this vector.
- * Returns a new vector. Does not change instance data.
- *
- * @param v Vector to be subtracted.
- * @return {@code this} - {@code v}.
- * @throws MathIllegalArgumentException if {@code v} is not the same size as
- * {@code this} vector.
- */
- public RealVector subtract(RealVector v) throws MathIllegalArgumentException {
- checkVectorDimensions(v);
- RealVector result = v.mapMultiply(-1d);
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- final int index = e.getIndex();
- result.setEntry(index, e.getValue() + result.getEntry(index));
- }
- return result;
- }
- /**
- * Add a value to each entry.
- * Returns a new vector. Does not change instance data.
- *
- * @param d Value to be added to each entry.
- * @return {@code this} + {@code d}.
- */
- public RealVector mapAdd(double d) {
- return copy().mapAddToSelf(d);
- }
- /**
- * Add a value to each entry.
- * The instance is changed in-place.
- *
- * @param d Value to be added to each entry.
- * @return {@code this}.
- */
- public RealVector mapAddToSelf(double d) {
- if (d != 0) {
- return mapToSelf(FunctionUtils.fix2ndArgument(new Add(), d));
- }
- return this;
- }
- /**
- * Returns a (deep) copy of this vector.
- *
- * @return a vector copy.
- */
- public abstract RealVector copy();
- /**
- * Compute the dot product of this vector with {@code v}.
- *
- * @param v Vector with which dot product should be computed
- * @return the scalar dot product between this instance and {@code v}.
- * @throws MathIllegalArgumentException if {@code v} is not the same size as
- * {@code this} vector.
- */
- public double dotProduct(RealVector v) throws MathIllegalArgumentException {
- checkVectorDimensions(v);
- double d = 0;
- final int n = getDimension();
- for (int i = 0; i < n; i++) {
- d += getEntry(i) * v.getEntry(i);
- }
- return d;
- }
- /**
- * Computes the cosine of the angle between this vector and the
- * argument.
- *
- * @param v Vector.
- * @return the cosine of the angle between this vector and {@code v}.
- * @throws MathRuntimeException if {@code this} or {@code v} is the null
- * vector
- * @throws MathIllegalArgumentException if the dimensions of {@code this} and
- * {@code v} do not match
- */
- public double cosine(RealVector v) throws MathIllegalArgumentException,
- MathRuntimeException {
- final double norm = getNorm();
- final double vNorm = v.getNorm();
- if (norm == 0 ||
- vNorm == 0) {
- throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
- }
- return dotProduct(v) / (norm * vNorm);
- }
- /**
- * Element-by-element division.
- *
- * @param v Vector by which instance elements must be divided.
- * @return a vector containing this[i] / v[i] for all i.
- * @throws MathIllegalArgumentException if {@code v} is not the same size as
- * {@code this} vector.
- */
- public abstract RealVector ebeDivide(RealVector v)
- throws MathIllegalArgumentException;
- /**
- * Element-by-element multiplication.
- *
- * @param v Vector by which instance elements must be multiplied
- * @return a vector containing this[i] * v[i] for all i.
- * @throws MathIllegalArgumentException if {@code v} is not the same size as
- * {@code this} vector.
- */
- public abstract RealVector ebeMultiply(RealVector v)
- throws MathIllegalArgumentException;
- /**
- * Distance between two vectors.
- * <p>This method computes the distance consistent with the
- * L<sub>2</sub> norm, i.e. the square root of the sum of
- * element differences, or Euclidean distance.</p>
- *
- * @param v Vector to which distance is requested.
- * @return the distance between two vectors.
- * @throws MathIllegalArgumentException if {@code v} is not the same size as
- * {@code this} vector.
- * @see #getL1Distance(RealVector)
- * @see #getLInfDistance(RealVector)
- * @see #getNorm()
- */
- public double getDistance(RealVector v) throws MathIllegalArgumentException {
- checkVectorDimensions(v);
- double d = 0;
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- final double diff = e.getValue() - v.getEntry(e.getIndex());
- d += diff * diff;
- }
- return FastMath.sqrt(d);
- }
- /**
- * Returns the L<sub>2</sub> norm of the vector.
- * <p>The L<sub>2</sub> norm is the root of the sum of
- * the squared elements.</p>
- *
- * @return the norm.
- * @see #getL1Norm()
- * @see #getLInfNorm()
- * @see #getDistance(RealVector)
- */
- public double getNorm() {
- double sum = 0;
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- final double value = e.getValue();
- sum += value * value;
- }
- return FastMath.sqrt(sum);
- }
- /**
- * Returns the L<sub>1</sub> norm of the vector.
- * <p>The L<sub>1</sub> norm is the sum of the absolute
- * values of the elements.</p>
- *
- * @return the norm.
- * @see #getNorm()
- * @see #getLInfNorm()
- * @see #getL1Distance(RealVector)
- */
- public double getL1Norm() {
- double norm = 0;
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- norm += FastMath.abs(e.getValue());
- }
- return norm;
- }
- /**
- * Returns the L<sub>∞</sub> norm of the vector.
- * <p>The L<sub>∞</sub> norm is the max of the absolute
- * values of the elements.</p>
- *
- * @return the norm.
- * @see #getNorm()
- * @see #getL1Norm()
- * @see #getLInfDistance(RealVector)
- */
- public double getLInfNorm() {
- double norm = 0;
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- norm = FastMath.max(norm, FastMath.abs(e.getValue()));
- }
- return norm;
- }
- /**
- * Distance between two vectors.
- * <p>This method computes the distance consistent with
- * L<sub>1</sub> norm, i.e. the sum of the absolute values of
- * the elements differences.</p>
- *
- * @param v Vector to which distance is requested.
- * @return the distance between two vectors.
- * @throws MathIllegalArgumentException if {@code v} is not the same size as
- * {@code this} vector.
- */
- public double getL1Distance(RealVector v)
- throws MathIllegalArgumentException {
- checkVectorDimensions(v);
- double d = 0;
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- d += FastMath.abs(e.getValue() - v.getEntry(e.getIndex()));
- }
- return d;
- }
- /**
- * Distance between two vectors.
- * <p>This method computes the distance consistent with
- * L<sub>∞</sub> norm, i.e. the max of the absolute values of
- * element differences.</p>
- *
- * @param v Vector to which distance is requested.
- * @return the distance between two vectors.
- * @throws MathIllegalArgumentException if {@code v} is not the same size as
- * {@code this} vector.
- * @see #getDistance(RealVector)
- * @see #getL1Distance(RealVector)
- * @see #getLInfNorm()
- */
- public double getLInfDistance(RealVector v)
- throws MathIllegalArgumentException {
- checkVectorDimensions(v);
- double d = 0;
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- d = FastMath.max(FastMath.abs(e.getValue() - v.getEntry(e.getIndex())), d);
- }
- return d;
- }
- /**
- * Get the index of the minimum entry.
- *
- * @return the index of the minimum entry or -1 if vector length is 0
- * or all entries are {@code NaN}.
- */
- public int getMinIndex() {
- int minIndex = -1;
- double minValue = Double.POSITIVE_INFINITY;
- Iterator<Entry> iterator = iterator();
- while (iterator.hasNext()) {
- final Entry entry = iterator.next();
- if (entry.getValue() <= minValue) {
- minIndex = entry.getIndex();
- minValue = entry.getValue();
- }
- }
- return minIndex;
- }
- /**
- * Get the value of the minimum entry.
- *
- * @return the value of the minimum entry or {@code NaN} if all
- * entries are {@code NaN}.
- */
- public double getMinValue() {
- final int minIndex = getMinIndex();
- return minIndex < 0 ? Double.NaN : getEntry(minIndex);
- }
- /**
- * Get the index of the maximum entry.
- *
- * @return the index of the maximum entry or -1 if vector length is 0
- * or all entries are {@code NaN}
- */
- public int getMaxIndex() {
- int maxIndex = -1;
- double maxValue = Double.NEGATIVE_INFINITY;
- Iterator<Entry> iterator = iterator();
- while (iterator.hasNext()) {
- final Entry entry = iterator.next();
- if (entry.getValue() >= maxValue) {
- maxIndex = entry.getIndex();
- maxValue = entry.getValue();
- }
- }
- return maxIndex;
- }
- /**
- * Get the value of the maximum entry.
- *
- * @return the value of the maximum entry or {@code NaN} if all
- * entries are {@code NaN}.
- */
- public double getMaxValue() {
- final int maxIndex = getMaxIndex();
- return maxIndex < 0 ? Double.NaN : getEntry(maxIndex);
- }
- /**
- * Multiply each entry by the argument. Returns a new vector.
- * Does not change instance data.
- *
- * @param d Multiplication factor.
- * @return {@code this} * {@code d}.
- */
- public RealVector mapMultiply(double d) {
- return copy().mapMultiplyToSelf(d);
- }
- /**
- * Multiply each entry.
- * The instance is changed in-place.
- *
- * @param d Multiplication factor.
- * @return {@code this}.
- */
- public RealVector mapMultiplyToSelf(double d){
- return mapToSelf(FunctionUtils.fix2ndArgument(new Multiply(), d));
- }
- /**
- * Subtract a value from each entry. Returns a new vector.
- * Does not change instance data.
- *
- * @param d Value to be subtracted.
- * @return {@code this} - {@code d}.
- */
- public RealVector mapSubtract(double d) {
- return copy().mapSubtractToSelf(d);
- }
- /**
- * Subtract a value from each entry.
- * The instance is changed in-place.
- *
- * @param d Value to be subtracted.
- * @return {@code this}.
- */
- public RealVector mapSubtractToSelf(double d){
- return mapAddToSelf(-d);
- }
- /**
- * Divide each entry by the argument. Returns a new vector.
- * Does not change instance data.
- *
- * @param d Value to divide by.
- * @return {@code this} / {@code d}.
- */
- public RealVector mapDivide(double d) {
- return copy().mapDivideToSelf(d);
- }
- /**
- * Divide each entry by the argument.
- * The instance is changed in-place.
- *
- * @param d Value to divide by.
- * @return {@code this}.
- */
- public RealVector mapDivideToSelf(double d){
- return mapToSelf(FunctionUtils.fix2ndArgument(new Divide(), d));
- }
- /**
- * Compute the outer product.
- *
- * @param v Vector with which outer product should be computed.
- * @return the matrix outer product between this instance and {@code v}.
- */
- public RealMatrix outerProduct(RealVector v) {
- final int m = this.getDimension();
- final int n = v.getDimension();
- final RealMatrix product;
- if (v instanceof SparseRealVector || this instanceof SparseRealVector) {
- product = new OpenMapRealMatrix(m, n);
- } else {
- product = new Array2DRowRealMatrix(m, n);
- }
- for (int i = 0; i < m; i++) {
- for (int j = 0; j < n; j++) {
- product.setEntry(i, j, this.getEntry(i) * v.getEntry(j));
- }
- }
- return product;
- }
- /**
- * Find the orthogonal projection of this vector onto another vector.
- *
- * @param v vector onto which instance must be projected.
- * @return projection of the instance onto {@code v}.
- * @throws MathIllegalArgumentException if {@code v} is not the same size as
- * {@code this} vector.
- * @throws MathRuntimeException if {@code this} or {@code v} is the null
- * vector
- */
- public RealVector projection(final RealVector v)
- throws MathIllegalArgumentException, MathRuntimeException {
- final double norm2 = v.dotProduct(v);
- if (norm2 == 0.0) {
- throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
- }
- return v.mapMultiply(dotProduct(v) / norm2);
- }
- /**
- * Set all elements to a single value.
- *
- * @param value Single value to set for all elements.
- */
- public void set(double value) {
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- e.setValue(value);
- }
- }
- /**
- * Convert the vector to an array of {@code double}s.
- * The array is independent from this vector data: the elements
- * are copied.
- *
- * @return an array containing a copy of the vector elements.
- */
- public double[] toArray() {
- int dim = getDimension();
- double[] values = new double[dim];
- for (int i = 0; i < dim; i++) {
- values[i] = getEntry(i);
- }
- return values;
- }
- /**
- * Creates a unit vector pointing in the direction of this vector.
- * The instance is not changed by this method.
- *
- * @return a unit vector pointing in direction of this vector.
- * @throws MathRuntimeException if the norm is zero.
- */
- public RealVector unitVector() throws MathRuntimeException {
- final double norm = getNorm();
- if (norm == 0) {
- throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
- }
- return mapDivide(norm);
- }
- /**
- * Converts this vector into a unit vector.
- * The instance itself is changed by this method.
- *
- * @throws MathRuntimeException if the norm is zero.
- */
- public void unitize() throws MathRuntimeException {
- final double norm = getNorm();
- if (norm == 0) {
- throw new MathRuntimeException(LocalizedCoreFormats.ZERO_NORM);
- }
- mapDivideToSelf(getNorm());
- }
- /**
- * Create a sparse iterator over the vector, which may omit some entries.
- * The ommitted entries are either exact zeroes (for dense implementations)
- * or are the entries which are not stored (for real sparse vectors).
- * No guarantees are made about order of iteration.
- *
- * <p>Note: derived classes are required to return an {@link Iterator} that
- * returns non-null {@link Entry} objects as long as {@link Iterator#hasNext()}
- * returns {@code true}.</p>
- *
- * @return a sparse iterator.
- */
- public Iterator<Entry> sparseIterator() {
- return new SparseEntryIterator();
- }
- /**
- * Generic dense iterator. Iteration is in increasing order
- * of the vector index.
- *
- * <p>Note: derived classes are required to return an {@link Iterator} that
- * returns non-null {@link Entry} objects as long as {@link Iterator#hasNext()}
- * returns {@code true}.</p>
- *
- * @return a dense iterator.
- */
- public Iterator<Entry> iterator() {
- final int dim = getDimension();
- return new Iterator<Entry>() {
- /** Current index. */
- private int i;
- /** Current entry. */
- private Entry e = new Entry();
- /** {@inheritDoc} */
- @Override
- public boolean hasNext() {
- return i < dim;
- }
- /** {@inheritDoc} */
- @Override
- public Entry next() {
- if (i < dim) {
- e.setIndex(i++);
- return e;
- } else {
- throw new NoSuchElementException();
- }
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all circumstances.
- */
- @Override
- public void remove() throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- };
- }
- /**
- * Acts as if implemented as:
- * <pre>
- * return copy().mapToSelf(function);
- * </pre>
- * Returns a new vector. Does not change instance data.
- *
- * @param function Function to apply to each entry.
- * @return a new vector.
- */
- public RealVector map(UnivariateFunction function) {
- return copy().mapToSelf(function);
- }
- /**
- * Acts as if it is implemented as:
- * <pre>
- * Entry e = null;
- * for(Iterator<Entry> it = iterator(); it.hasNext(); e = it.next()) {
- * e.setValue(function.value(e.getValue()));
- * }
- * </pre>
- * Entries of this vector are modified in-place by this method.
- *
- * @param function Function to apply to each entry.
- * @return a reference to this vector.
- */
- public RealVector mapToSelf(UnivariateFunction function) {
- Iterator<Entry> it = iterator();
- while (it.hasNext()) {
- final Entry e = it.next();
- e.setValue(function.value(e.getValue()));
- }
- return this;
- }
- /**
- * Returns a new vector representing {@code a * this + b * y}, the linear
- * combination of {@code this} and {@code y}.
- * Returns a new vector. Does not change instance data.
- *
- * @param a Coefficient of {@code this}.
- * @param b Coefficient of {@code y}.
- * @param y Vector with which {@code this} is linearly combined.
- * @return a vector containing {@code a * this[i] + b * y[i]} for all
- * {@code i}.
- * @throws MathIllegalArgumentException if {@code y} is not the same size as
- * {@code this} vector.
- */
- public RealVector combine(double a, double b, RealVector y)
- throws MathIllegalArgumentException {
- return copy().combineToSelf(a, b, y);
- }
- /**
- * Updates {@code this} with the linear combination of {@code this} and
- * {@code y}.
- *
- * @param a Weight of {@code this}.
- * @param b Weight of {@code y}.
- * @param y Vector with which {@code this} is linearly combined.
- * @return {@code this}, with components equal to
- * {@code a * this[i] + b * y[i]} for all {@code i}.
- * @throws MathIllegalArgumentException if {@code y} is not the same size as
- * {@code this} vector.
- */
- public RealVector combineToSelf(double a, double b, RealVector y)
- throws MathIllegalArgumentException {
- checkVectorDimensions(y);
- for (int i = 0; i < getDimension(); i++) {
- final double xi = getEntry(i);
- final double yi = y.getEntry(i);
- setEntry(i, a * xi + b * yi);
- }
- return this;
- }
- /**
- * Visits (but does not alter) all entries of this vector in default order
- * (increasing index).
- *
- * @param visitor the visitor to be used to process the entries of this
- * vector
- * @return the value returned by {@link RealVectorPreservingVisitor#end()}
- * at the end of the walk
- */
- public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor) {
- final int dim = getDimension();
- visitor.start(dim, 0, dim - 1);
- for (int i = 0; i < dim; i++) {
- visitor.visit(i, getEntry(i));
- }
- return visitor.end();
- }
- /**
- * Visits (but does not alter) some entries of this vector in default order
- * (increasing index).
- *
- * @param visitor visitor to be used to process the entries of this vector
- * @param start the index of the first entry to be visited
- * @param end the index of the last entry to be visited (inclusive)
- * @return the value returned by {@link RealVectorPreservingVisitor#end()}
- * at the end of the walk
- * @throws MathIllegalArgumentException if {@code end < start}.
- * @throws MathIllegalArgumentException if the indices are not valid.
- */
- public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor,
- final int start, final int end)
- throws MathIllegalArgumentException {
- checkIndices(start, end);
- visitor.start(getDimension(), start, end);
- for (int i = start; i <= end; i++) {
- visitor.visit(i, getEntry(i));
- }
- return visitor.end();
- }
- /**
- * Visits (but does not alter) all entries of this vector in optimized
- * order. The order in which the entries are visited is selected so as to
- * lead to the most efficient implementation; it might depend on the
- * concrete implementation of this abstract class.
- *
- * @param visitor the visitor to be used to process the entries of this
- * vector
- * @return the value returned by {@link RealVectorPreservingVisitor#end()}
- * at the end of the walk
- */
- public double walkInOptimizedOrder(final RealVectorPreservingVisitor visitor) {
- return walkInDefaultOrder(visitor);
- }
- /**
- * Visits (but does not alter) some entries of this vector in optimized
- * order. The order in which the entries are visited is selected so as to
- * lead to the most efficient implementation; it might depend on the
- * concrete implementation of this abstract class.
- *
- * @param visitor visitor to be used to process the entries of this vector
- * @param start the index of the first entry to be visited
- * @param end the index of the last entry to be visited (inclusive)
- * @return the value returned by {@link RealVectorPreservingVisitor#end()}
- * at the end of the walk
- * @throws MathIllegalArgumentException if {@code end < start}.
- * @throws MathIllegalArgumentException if the indices are not valid.
- */
- public double walkInOptimizedOrder(final RealVectorPreservingVisitor visitor,
- final int start, final int end)
- throws MathIllegalArgumentException {
- return walkInDefaultOrder(visitor, start, end);
- }
- /**
- * Visits (and possibly alters) all entries of this vector in default order
- * (increasing index).
- *
- * @param visitor the visitor to be used to process and modify the entries
- * of this vector
- * @return the value returned by {@link RealVectorChangingVisitor#end()}
- * at the end of the walk
- */
- public double walkInDefaultOrder(final RealVectorChangingVisitor visitor) {
- final int dim = getDimension();
- visitor.start(dim, 0, dim - 1);
- for (int i = 0; i < dim; i++) {
- setEntry(i, visitor.visit(i, getEntry(i)));
- }
- return visitor.end();
- }
- /**
- * Visits (and possibly alters) some entries of this vector in default order
- * (increasing index).
- *
- * @param visitor visitor to be used to process the entries of this vector
- * @param start the index of the first entry to be visited
- * @param end the index of the last entry to be visited (inclusive)
- * @return the value returned by {@link RealVectorChangingVisitor#end()}
- * at the end of the walk
- * @throws MathIllegalArgumentException if {@code end < start}.
- * @throws MathIllegalArgumentException if the indices are not valid.
- */
- public double walkInDefaultOrder(final RealVectorChangingVisitor visitor,
- final int start, final int end)
- throws MathIllegalArgumentException {
- checkIndices(start, end);
- visitor.start(getDimension(), start, end);
- for (int i = start; i <= end; i++) {
- setEntry(i, visitor.visit(i, getEntry(i)));
- }
- return visitor.end();
- }
- /**
- * Visits (and possibly alters) all entries of this vector in optimized
- * order. The order in which the entries are visited is selected so as to
- * lead to the most efficient implementation; it might depend on the
- * concrete implementation of this abstract class.
- *
- * @param visitor the visitor to be used to process the entries of this
- * vector
- * @return the value returned by {@link RealVectorChangingVisitor#end()}
- * at the end of the walk
- */
- public double walkInOptimizedOrder(final RealVectorChangingVisitor visitor) {
- return walkInDefaultOrder(visitor);
- }
- /**
- * Visits (and possibly change) some entries of this vector in optimized
- * order. The order in which the entries are visited is selected so as to
- * lead to the most efficient implementation; it might depend on the
- * concrete implementation of this abstract class.
- *
- * @param visitor visitor to be used to process the entries of this vector
- * @param start the index of the first entry to be visited
- * @param end the index of the last entry to be visited (inclusive)
- * @return the value returned by {@link RealVectorChangingVisitor#end()}
- * at the end of the walk
- * @throws MathIllegalArgumentException if {@code end < start}.
- * @throws MathIllegalArgumentException if the indices are not valid.
- */
- public double walkInOptimizedOrder(final RealVectorChangingVisitor visitor,
- final int start, final int end)
- throws MathIllegalArgumentException {
- return walkInDefaultOrder(visitor, start, end);
- }
- /** An entry in the vector. */
- public class Entry {
- /** Index of this entry. */
- private int index;
- /** Simple constructor. */
- public Entry() {
- setIndex(0);
- }
- /**
- * Get the value of the entry.
- *
- * @return the value of the entry.
- */
- public double getValue() {
- return getEntry(getIndex());
- }
- /**
- * Set the value of the entry.
- *
- * @param value New value for the entry.
- */
- public void setValue(double value) {
- setEntry(getIndex(), value);
- }
- /**
- * Get the index of the entry.
- *
- * @return the index of the entry.
- */
- public int getIndex() {
- return index;
- }
- /**
- * Set the index of the entry.
- *
- * @param index New index for the entry.
- */
- public void setIndex(int index) {
- this.index = index;
- }
- }
- /**
- * <p>
- * Test for the equality of two real vectors. If all coordinates of two real
- * vectors are exactly the same, and none are {@code NaN}, the two real
- * vectors are considered to be equal. {@code NaN} coordinates are
- * considered to affect globally the vector and be equals to each other -
- * i.e, if either (or all) coordinates of the real vector are equal to
- * {@code NaN}, the real vector is equal to a vector with all {@code NaN}
- * coordinates.
- * </p>
- * <p>
- * This method <em>must</em> be overriden by concrete subclasses of
- * {@link RealVector} (the current implementation throws an exception).
- * </p>
- *
- * @param other Object to test for equality.
- * @return {@code true} if two vector objects are equal, {@code false} if
- * {@code other} is null, not an instance of {@code RealVector}, or
- * not equal to this {@code RealVector} instance.
- * @throws MathRuntimeException if this method is not
- * overridden.
- */
- @Override
- public boolean equals(Object other)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /**
- * {@inheritDoc}. This method <em>must</em> be overriden by concrete
- * subclasses of {@link RealVector} (current implementation throws an
- * exception).
- *
- * @throws MathRuntimeException if this method is not
- * overridden.
- */
- @Override
- public int hashCode() throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /**
- * This class should rarely be used, but is here to provide
- * a default implementation of sparseIterator(), which is implemented
- * by walking over the entries, skipping those that are zero.
- *
- * Concrete subclasses which are SparseVector implementations should
- * make their own sparse iterator, rather than using this one.
- *
- * This implementation might be useful for ArrayRealVector, when expensive
- * operations which preserve the default value are to be done on the entries,
- * and the fraction of non-default values is small (i.e. someone took a
- * SparseVector, and passed it into the copy-constructor of ArrayRealVector)
- */
- protected class SparseEntryIterator implements Iterator<Entry> {
- /** Dimension of the vector. */
- private final int dim;
- /** Last entry returned by {@link #next()}. */
- private Entry current;
- /** Next entry for {@link #next()} to return. */
- private Entry next;
- /** Simple constructor. */
- protected SparseEntryIterator() {
- dim = getDimension();
- current = new Entry();
- next = new Entry();
- if (next.getValue() == 0) {
- advance(next);
- }
- }
- /**
- * Advance an entry up to the next nonzero one.
- *
- * @param e entry to advance.
- */
- protected void advance(Entry e) {
- if (e == null) {
- return;
- }
- do {
- e.setIndex(e.getIndex() + 1);
- } while (e.getIndex() < dim && e.getValue() == 0);
- if (e.getIndex() >= dim) {
- e.setIndex(-1);
- }
- }
- /** {@inheritDoc} */
- @Override
- public boolean hasNext() {
- return next.getIndex() >= 0;
- }
- /** {@inheritDoc} */
- @Override
- public Entry next() {
- int index = next.getIndex();
- if (index < 0) {
- throw new NoSuchElementException();
- }
- current.setIndex(index);
- advance(next);
- return current;
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all circumstances.
- */
- @Override
- public void remove() throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- }
- /**
- * Returns an unmodifiable view of the specified vector.
- * The returned vector has read-only access. An attempt to modify it will
- * result in a {@link MathRuntimeException}. However, the
- * returned vector is <em>not</em> immutable, since any modification of
- * {@code v} will also change the returned view.
- * For example, in the following piece of code
- * <pre>
- * RealVector v = new ArrayRealVector(2);
- * RealVector w = RealVector.unmodifiableRealVector(v);
- * v.setEntry(0, 1.2);
- * v.setEntry(1, -3.4);
- * </pre>
- * the changes will be seen in the {@code w} view of {@code v}.
- *
- * @param v Vector for which an unmodifiable view is to be returned.
- * @return an unmodifiable view of {@code v}.
- */
- public static RealVector unmodifiableRealVector(final RealVector v) {
- /**
- * This anonymous class is an implementation of {@link RealVector}
- * with read-only access.
- * It wraps any {@link RealVector}, and exposes all methods which
- * do not modify it. Invoking methods which should normally result
- * in the modification of the calling {@link RealVector} results in
- * a {@link MathRuntimeException}. It should be noted
- * that {@link UnmodifiableVector} is <em>not</em> immutable.
- */
- return new RealVector() {
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all circumstances.
- */
- @Override
- public RealVector mapToSelf(UnivariateFunction function)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector map(UnivariateFunction function) {
- return v.map(function);
- }
- /** {@inheritDoc} */
- @Override
- public Iterator<Entry> iterator() {
- final Iterator<Entry> i = v.iterator();
- return new Iterator<Entry>() {
- /** The current entry. */
- private final UnmodifiableEntry e = new UnmodifiableEntry();
- /** {@inheritDoc} */
- @Override
- public boolean hasNext() {
- return i.hasNext();
- }
- /** {@inheritDoc} */
- @Override
- public Entry next() {
- e.setIndex(i.next().getIndex());
- return e;
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public void remove() throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- };
- }
- /** {@inheritDoc} */
- @Override
- public Iterator<Entry> sparseIterator() {
- final Iterator<Entry> i = v.sparseIterator();
- return new Iterator<Entry>() {
- /** The current entry. */
- private final UnmodifiableEntry e = new UnmodifiableEntry();
- /** {@inheritDoc} */
- @Override
- public boolean hasNext() {
- return i.hasNext();
- }
- /** {@inheritDoc} */
- @Override
- public Entry next() {
- e.setIndex(i.next().getIndex());
- return e;
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public void remove()
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- };
- }
- /** {@inheritDoc} */
- @Override
- public RealVector copy() {
- return v.copy();
- }
- /** {@inheritDoc} */
- @Override
- public RealVector add(RealVector w)
- throws MathIllegalArgumentException {
- return v.add(w);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector subtract(RealVector w)
- throws MathIllegalArgumentException {
- return v.subtract(w);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector mapAdd(double d) {
- return v.mapAdd(d);
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public RealVector mapAddToSelf(double d)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector mapSubtract(double d) {
- return v.mapSubtract(d);
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public RealVector mapSubtractToSelf(double d)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector mapMultiply(double d) {
- return v.mapMultiply(d);
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public RealVector mapMultiplyToSelf(double d)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector mapDivide(double d) {
- return v.mapDivide(d);
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public RealVector mapDivideToSelf(double d)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector ebeMultiply(RealVector w)
- throws MathIllegalArgumentException {
- return v.ebeMultiply(w);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector ebeDivide(RealVector w)
- throws MathIllegalArgumentException {
- return v.ebeDivide(w);
- }
- /** {@inheritDoc} */
- @Override
- public double dotProduct(RealVector w)
- throws MathIllegalArgumentException {
- return v.dotProduct(w);
- }
- /** {@inheritDoc} */
- @Override
- public double cosine(RealVector w)
- throws MathRuntimeException {
- return v.cosine(w);
- }
- /** {@inheritDoc} */
- @Override
- public double getNorm() {
- return v.getNorm();
- }
- /** {@inheritDoc} */
- @Override
- public double getL1Norm() {
- return v.getL1Norm();
- }
- /** {@inheritDoc} */
- @Override
- public double getLInfNorm() {
- return v.getLInfNorm();
- }
- /** {@inheritDoc} */
- @Override
- public double getDistance(RealVector w)
- throws MathIllegalArgumentException {
- return v.getDistance(w);
- }
- /** {@inheritDoc} */
- @Override
- public double getL1Distance(RealVector w)
- throws MathIllegalArgumentException {
- return v.getL1Distance(w);
- }
- /** {@inheritDoc} */
- @Override
- public double getLInfDistance(RealVector w)
- throws MathIllegalArgumentException {
- return v.getLInfDistance(w);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector unitVector() throws MathRuntimeException {
- return v.unitVector();
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public void unitize() throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /** {@inheritDoc} */
- @Override
- public RealMatrix outerProduct(RealVector w) {
- return v.outerProduct(w);
- }
- /** {@inheritDoc} */
- @Override
- public double getEntry(int index) throws MathIllegalArgumentException {
- return v.getEntry(index);
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public void setEntry(int index, double value)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public void addToEntry(int index, double value)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /** {@inheritDoc} */
- @Override
- public int getDimension() {
- return v.getDimension();
- }
- /** {@inheritDoc} */
- @Override
- public RealVector append(RealVector w) {
- return v.append(w);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector append(double d) {
- return v.append(d);
- }
- /** {@inheritDoc} */
- @Override
- public RealVector getSubVector(int index, int n)
- throws MathIllegalArgumentException {
- return v.getSubVector(index, n);
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public void setSubVector(int index, RealVector w)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public void set(double value)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /** {@inheritDoc} */
- @Override
- public double[] toArray() {
- return v.toArray();
- }
- /** {@inheritDoc} */
- @Override
- public boolean isNaN() {
- return v.isNaN();
- }
- /** {@inheritDoc} */
- @Override
- public boolean isInfinite() {
- return v.isInfinite();
- }
- /** {@inheritDoc} */
- @Override
- public RealVector combine(double a, double b, RealVector y)
- throws MathIllegalArgumentException {
- return v.combine(a, b, y);
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public RealVector combineToSelf(double a, double b, RealVector y)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- /** An entry in the vector. */
- class UnmodifiableEntry extends Entry {
- /** {@inheritDoc} */
- @Override
- public double getValue() {
- return v.getEntry(getIndex());
- }
- /**
- * {@inheritDoc}
- *
- * @throws MathRuntimeException in all
- * circumstances.
- */
- @Override
- public void setValue(double value)
- throws MathRuntimeException {
- throw new MathRuntimeException(LocalizedCoreFormats.UNSUPPORTED_OPERATION);
- }
- }
- };
- }
- }