diff --git a/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java b/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
new file mode 100644
index 000000000..ac16932c9
--- /dev/null
+++ b/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
@@ -0,0 +1,818 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+
+package org.apache.commons.math.linear;
+
+import java.util.Iterator;
+
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.MathRuntimeException;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.analysis.UnivariateRealFunctions;
+
+/**
+ * This class provides default basic implementations for many methods in the
+ * {@link RealVector} interface with.
+ * @version $Revision$ $Date$
+ * @since 2.1
+ */
+public abstract class AbstractRealVector implements RealVector {
+
+ /**
+ * Check if instance and specified vectors have the same dimension.
+ * @param v vector to compare instance with
+ * @exception IllegalArgumentException if the vectors do not
+ * have the same dimension
+ */
+ protected void checkVectorDimensions(RealVector v) {
+ checkVectorDimensions(v.getDimension());
+ }
+
+ /**
+ * Check if instance dimension is equal to some expected value.
+ *
+ * @param n expected dimension.
+ * @exception IllegalArgumentException if the dimension is
+ * inconsistent with vector size
+ */
+ protected void checkVectorDimensions(int n)
+ throws IllegalArgumentException {
+ double d = getDimension();
+ if (d != n) {
+ throw MathRuntimeException.createIllegalArgumentException(
+ "vector length mismatch: got {0} but expected {1}",
+ d, n);
+ }
+ }
+
+ /**
+ * Check if an index is valid.
+ * @param index index to check
+ * @exception MatrixIndexException if index is not valid
+ */
+ protected void checkIndex(final int index)
+ throws MatrixIndexException {
+ if (index < 0 || index >= getDimension()) {
+ throw new MatrixIndexException(
+ "index {0} out of allowed range [{1}, {2}]",
+ index, 0, getDimension() - 1);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void setSubVector(int index, RealVector v) throws MatrixIndexException {
+ checkIndex(index);
+ checkIndex(index + v.getDimension() - 1);
+ setSubVector(index, v.getData());
+ }
+
+ /** {@inheritDoc} */
+ public void setSubVector(int index, double[] v) throws MatrixIndexException {
+ checkIndex(index);
+ checkIndex(index + v.length - 1);
+ for (int i = 0; i < v.length; i++) {
+ setEntry(i + index, v[i]);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector add(double[] v) throws IllegalArgumentException {
+ double[] result = v.clone();
+ Iterator it = sparseIterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ result[e.getIndex()] += e.getValue();
+ }
+ return new ArrayRealVector(result, false);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector add(RealVector v) throws IllegalArgumentException {
+ if (v instanceof ArrayRealVector) {
+ double[] values = ((ArrayRealVector)v).getDataRef();
+ return add(values);
+ }
+ RealVector result = v.copy();
+ Iterator it = sparseIterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ final int index = e.getIndex();
+ result.setEntry(index, e.getValue() + result.getEntry(index));
+ }
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public RealVector subtract(double[] v) throws IllegalArgumentException {
+ double[] result = v.clone();
+ Iterator it = sparseIterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ final int index = e.getIndex();
+ result[index] = e.getValue() - result[index];
+ }
+ return new ArrayRealVector(result, false);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector subtract(RealVector v) throws IllegalArgumentException {
+ if (v instanceof ArrayRealVector) {
+ double[] values = ((ArrayRealVector)v).getDataRef();
+ return add(values);
+ }
+ RealVector result = v.copy();
+ Iterator it = sparseIterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ final int index = e.getIndex();
+ v.setEntry(index, e.getValue() - result.getEntry(index));
+ }
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAdd(double d) {
+ return copy().mapAddToSelf(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAddToSelf(double d) {
+ if (d != 0) {
+ Iterator it = iterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ e.setValue(e.getValue() + d);
+ }
+ }
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ public abstract AbstractRealVector copy();
+
+ /** {@inheritDoc} */
+ public double dotProduct(double[] v) throws IllegalArgumentException {
+ return dotProduct(new ArrayRealVector(v, false));
+ }
+
+ /** {@inheritDoc} */
+ public double dotProduct(RealVector v) throws IllegalArgumentException {
+ checkVectorDimensions(v);
+ double d = 0;
+ Iterator it = sparseIterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ d += e.getValue() * v.getEntry(e.getIndex());
+ }
+ return d;
+ }
+
+ /** {@inheritDoc} */
+ public RealVector ebeDivide(double[] v) throws IllegalArgumentException {
+ return ebeDivide(new ArrayRealVector(v, false));
+ }
+
+ /** {@inheritDoc} */
+ public RealVector ebeMultiply(double[] v) throws IllegalArgumentException {
+ return ebeMultiply(new ArrayRealVector(v, false));
+ }
+
+ /** {@inheritDoc} */
+ public double getDistance(RealVector v) throws IllegalArgumentException {
+ checkVectorDimensions(v);
+ double d = 0;
+ Iterator it = sparseIterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ final double diff = e.getValue() - v.getEntry(e.getIndex());
+ d += diff * diff;
+ }
+ return Math.sqrt(d);
+ }
+
+ /** {@inheritDoc} */
+ public double getDistance(double[] v) throws IllegalArgumentException {
+ checkVectorDimensions(v.length);
+ double d = 0;
+ Iterator it = iterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ final double diff = e.getValue() - v[e.getIndex()];
+ d += diff * diff;
+ }
+ return Math.sqrt(d);
+ }
+
+ /** {@inheritDoc} */
+ public double getL1Distance(RealVector v) throws IllegalArgumentException {
+ checkVectorDimensions(v);
+ double d = 0;
+ Iterator it = iterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ d += Math.abs(e.getValue() - v.getEntry(e.getIndex()));
+ }
+ return d;
+ }
+
+ /** {@inheritDoc} */
+ public double getL1Distance(double[] v) throws IllegalArgumentException {
+ checkVectorDimensions(v.length);
+ double d = 0;
+ Iterator it = iterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ d += Math.abs(e.getValue() - v[e.getIndex()]);
+ }
+ return d;
+ }
+
+ /** {@inheritDoc} */
+ public double getLInfDistance(RealVector v) throws IllegalArgumentException {
+ checkVectorDimensions(v);
+ double d = 0;
+ Iterator it = iterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ d = Math.max(Math.abs(e.getValue() - v.getEntry(e.getIndex())), d);
+ }
+ return d;
+ }
+
+ /** {@inheritDoc} */
+ public double getLInfDistance(double[] v) throws IllegalArgumentException {
+ checkVectorDimensions(v.length);
+ double d = 0;
+ Iterator it = iterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ d = Math.max(Math.abs(e.getValue() - v[e.getIndex()]), d);
+ }
+ return d;
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAbs() {
+ return copy().mapAbsToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAbsToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.ABS);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAcos() {
+ return copy().mapAcosToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAcosToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.ACOS);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAsin() {
+ return copy().mapAsinToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAsinToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.ASIN);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAtan() {
+ return copy().mapAtanToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAtanToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.ATAN);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapCbrt() {
+ return copy().mapCbrtToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapCbrtToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.CBRT);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapCeil() {
+ return copy().mapCeilToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapCeilToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.CEIL);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapCos() {
+ return copy().mapCosToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapCosToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.COS);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapCosh() {
+ return copy().mapCoshToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapCoshToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.COSH);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapDivide(double d) {
+ return copy().mapDivideToSelf(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapExp() {
+ return copy().mapExpToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapExpToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.EXP);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapExpm1() {
+ return copy().mapExpm1ToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapExpm1ToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.EXP1M);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapFloor() {
+ return copy().mapFloorToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapFloorToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.FLOOR);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapInv() {
+ return copy().mapInvToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapLog() {
+ return copy().mapLogToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapLogToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.LOG);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapLog10() {
+ return copy().mapLog10ToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapLog10ToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.LOG10);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapLog1p() {
+ return copy().mapLog1pToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapLog1pToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.ASIN);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapMultiply(double d) {
+ return copy().mapMultiplyToSelf(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapPow(double d) {
+ return copy().mapPowToSelf(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapRint() {
+ return copy().mapRintToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapRintToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.RINT);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSignum() {
+ return copy().mapSignumToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSignumToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.SIGNUM);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSin() {
+ return copy().mapSinToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSinToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.SIN);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSinh() {
+ return copy().mapSinhToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSinhToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.SINH);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSqrt() {
+ return copy().mapSqrtToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSqrtToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.SQRT);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSubtract(double d) {
+ return copy().mapSubtractToSelf(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapTan() {
+ return copy().mapTanToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapTanToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.TAN);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapTanh() {
+ return copy().mapTanhToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapTanhToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.TANH);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapUlp() {
+ return copy().mapUlpToSelf();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapUlpToSelf() {
+ try {
+ return mapToSelf(UnivariateRealFunctions.ULP);
+ } catch (FunctionEvaluationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public RealMatrix outerProduct(RealVector v) throws IllegalArgumentException {
+ RealMatrix product;
+ if (v instanceof SparseRealVector || this instanceof SparseRealVector) {
+ product = new OpenMapRealMatrix(this.getDimension(), v.getDimension());
+ } else {
+ product = new Array2DRowRealMatrix(this.getDimension(), v.getDimension());
+ }
+ Iterator thisIt = sparseIterator();
+ Entry thisE = null;
+ while (thisIt.hasNext() && (thisE = thisIt.next()) != null) {
+ Iterator otherIt = v.sparseIterator();
+ Entry otherE = null;
+ while (otherIt.hasNext() && (otherE = otherIt.next()) != null) {
+ product.setEntry(thisE.getIndex(), otherE.getIndex(),
+ thisE.getValue() * otherE.getValue());
+ }
+ }
+
+ return product;
+
+ }
+
+ /** {@inheritDoc} */
+ public RealMatrix outerProduct(double[] v) throws IllegalArgumentException {
+ return outerProduct(new ArrayRealVector(v, false));
+ }
+
+ /** {@inheritDoc} */
+ public RealVector projection(double[] v) throws IllegalArgumentException {
+ return projection(new ArrayRealVector(v, false));
+ }
+
+ /** {@inheritDoc} */
+ public void set(double value) {
+ Iterator it = iterator();
+ Entry e = null;
+ while (it.hasNext() && (e = it.next()) != null) {
+ e.setValue(value);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public double[] toArray() {
+ int dim = getDimension();
+ double[] values = new double[dim];
+ for (int i = 0; i < dim; i++) {
+ values[i] = getEntry(i);
+ }
+ return values;
+ }
+
+ /** {@inheritDoc} */
+ public double[] getData() {
+ return toArray();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector unitVector() {
+ RealVector copy = copy();
+ copy.unitize();
+ return copy;
+ }
+
+ /** {@inheritDoc} */
+ public void unitize() {
+ mapDivideToSelf(getNorm());
+ }
+
+ /** {@inheritDoc} */
+ public Iterator sparseIterator() {
+ return new SparseEntryIterator();
+ }
+
+ /** {@inheritDoc} */
+ public Iterator iterator() {
+ final int dim = getDimension();
+ return new Iterator() {
+
+ /** Current index. */
+ private int i = 0;
+
+ /** Current entry. */
+ private EntryImpl e = new EntryImpl();
+
+ /** {@inheritDoc} */
+ public boolean hasNext() {
+ return i < dim;
+ }
+
+ /** {@inheritDoc} */
+ public Entry next() {
+ e.setIndex(i++);
+ return e;
+ }
+
+ /** {@inheritDoc} */
+ public void remove() {
+ throw new UnsupportedOperationException("Not supported");
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
+ public RealVector map(UnivariateRealFunction function) throws FunctionEvaluationException {
+ return copy().mapToSelf(function);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapToSelf(UnivariateRealFunction function) throws FunctionEvaluationException {
+ Iterator it = (function.value(0) == 0) ? sparseIterator() : iterator();
+ Entry e;
+ while (it.hasNext() && (e = it.next()) != null) {
+ e.setValue(function.value(e.getValue()));
+ }
+ return this;
+ }
+
+ /** An entry in the vector. */
+ protected class EntryImpl extends Entry {
+
+ /** Simple constructor. */
+ public EntryImpl() {
+ setIndex(0);
+ }
+
+ /** {@inheritDoc} */
+ public double getValue() {
+ return getEntry(getIndex());
+ }
+
+ /** {@inheritDoc} */
+ public void setValue(double newValue) {
+ setEntry(getIndex(), newValue);
+ }
+ }
+
+ /**
+ * This class should rare be used, but is here to provide
+ * a default implementation of sparseIterator(), which is implemented
+ * by walking over the entries, skipping those whose values are the default one.
+ *
+ * Concrete subclasses which are SparseVector implementations should
+ * make their own sparse iterator, not use 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 {
+
+ /** Dimension of the vector. */
+ private final int dim;
+
+ /** Temporary entry (reused on each call to {@link #next()}. */
+ private EntryImpl tmp = new EntryImpl();
+
+ /** Current entry. */
+ private EntryImpl current;
+
+ /** Next entry. */
+ private EntryImpl next;
+
+ /** Simple constructor. */
+ protected SparseEntryIterator() {
+ dim = getDimension();
+ current = new EntryImpl();
+ if (current.getValue() == 0) {
+ advance(current);
+ }
+ next = new EntryImpl();
+ next.setIndex(current.getIndex());
+ advance(next);
+ }
+
+ /** Advance an entry up to the next non null one.
+ * @param e entry to advance
+ */
+ protected void advance(EntryImpl 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} */
+ public boolean hasNext() {
+ return current != null;
+ }
+
+ /** {@inheritDoc} */
+ public Entry next() {
+ tmp.setIndex(current.getIndex());
+ if (next != null) {
+ current.setIndex(next.getIndex());
+ advance(next);
+ if (next.getIndex() < 0) {
+ next = null;
+ }
+ } else {
+ current = null;
+ }
+ return tmp;
+ }
+
+ /** {@inheritDoc} */
+ public void remove() {
+ throw new UnsupportedOperationException("Not supported");
+ }
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/math/linear/ArrayRealVector.java b/src/main/java/org/apache/commons/math/linear/ArrayRealVector.java
index cd4fb68a0..14b0f393d 100644
--- a/src/main/java/org/apache/commons/math/linear/ArrayRealVector.java
+++ b/src/main/java/org/apache/commons/math/linear/ArrayRealVector.java
@@ -18,6 +18,7 @@ package org.apache.commons.math.linear;
import java.io.Serializable;
import java.util.Arrays;
+import java.util.Iterator;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.util.MathUtils;
@@ -27,7 +28,7 @@ import org.apache.commons.math.util.MathUtils;
* @version $Revision$ $Date$
* @since 2.0
*/
-public class ArrayRealVector implements RealVector, Serializable {
+public class ArrayRealVector extends AbstractRealVector implements Serializable {
/** Message for non fitting position and size. */
private static final String NON_FITTING_POSITION_AND_SIZE_MESSAGE =
@@ -166,7 +167,7 @@ public class ArrayRealVector implements RealVector, Serializable {
* @param v vector to copy
*/
public ArrayRealVector(ArrayRealVector v) {
- data = v.data.clone();
+ this(v, true);
}
/**
@@ -223,20 +224,22 @@ public class ArrayRealVector implements RealVector, Serializable {
}
/** {@inheritDoc} */
- public RealVector copy() {
+ public AbstractRealVector copy() {
return new ArrayRealVector(this, true);
}
/** {@inheritDoc} */
public RealVector add(RealVector v)
throws IllegalArgumentException {
- try {
+ if(v instanceof ArrayRealVector) {
return add((ArrayRealVector) v);
- } catch (ClassCastException cce) {
+ } else {
checkVectorDimensions(v);
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = data[i] + v.getEntry(i);
+ double[] out = data.clone();
+ Iterator it = v.sparseIterator();
+ Entry e;
+ while(it.hasNext() && (e = it.next()) != null) {
+ out[e.getIndex()] += e.getValue();
}
return new ArrayRealVector(out);
}
@@ -246,9 +249,9 @@ public class ArrayRealVector implements RealVector, Serializable {
public RealVector add(double[] v)
throws IllegalArgumentException {
checkVectorDimensions(v.length);
- double[] out = new double[data.length];
+ double[] out = data.clone();
for (int i = 0; i < data.length; i++) {
- out[i] = data[i] + v[i];
+ out[i] += v[i];
}
return new ArrayRealVector(out);
}
@@ -267,13 +270,15 @@ public class ArrayRealVector implements RealVector, Serializable {
/** {@inheritDoc} */
public RealVector subtract(RealVector v)
throws IllegalArgumentException {
- try {
+ if(v instanceof ArrayRealVector) {
return subtract((ArrayRealVector) v);
- } catch (ClassCastException cce) {
+ } else {
checkVectorDimensions(v);
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = data[i] - v.getEntry(i);
+ double[] out = data.clone();
+ Iterator it = v.sparseIterator();
+ Entry e;
+ while(it.hasNext() && (e = it.next()) != null) {
+ out[e.getIndex()] -= e.getValue();
}
return new ArrayRealVector(out);
}
@@ -283,9 +288,9 @@ public class ArrayRealVector implements RealVector, Serializable {
public RealVector subtract(double[] v)
throws IllegalArgumentException {
checkVectorDimensions(v.length);
- double[] out = new double[data.length];
+ double[] out = data.clone();
for (int i = 0; i < data.length; i++) {
- out[i] = data[i] - v[i];
+ out[i] -= v[i];
}
return new ArrayRealVector(out);
}
@@ -301,15 +306,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return (ArrayRealVector) subtract(v.data);
}
- /** {@inheritDoc} */
- public RealVector mapAdd(double d) {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = data[i] + d;
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapAddToSelf(double d) {
for (int i = 0; i < data.length; i++) {
@@ -318,15 +314,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapSubtract(double d) {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = data[i] - d;
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapSubtractToSelf(double d) {
for (int i = 0; i < data.length; i++) {
@@ -335,15 +322,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapMultiply(double d) {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = data[i] * d;
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapMultiplyToSelf(double d) {
for (int i = 0; i < data.length; i++) {
@@ -352,15 +330,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapDivide(double d) {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = data[i] / d;
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapDivideToSelf(double d) {
for (int i = 0; i < data.length; i++) {
@@ -369,15 +338,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapPow(double d) {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.pow(data[i], d);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapPowToSelf(double d) {
for (int i = 0; i < data.length; i++) {
@@ -386,15 +346,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapExp() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.exp(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapExpToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -403,15 +354,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapExpm1() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.expm1(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapExpm1ToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -420,15 +362,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapLog() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.log(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapLogToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -437,15 +370,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapLog10() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.log10(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapLog10ToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -454,15 +378,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapLog1p() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.log1p(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapLog1pToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -471,15 +386,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapCosh() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.cosh(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapCoshToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -488,15 +394,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapSinh() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.sinh(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapSinhToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -505,15 +402,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapTanh() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.tanh(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapTanhToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -522,15 +410,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapCos() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.cos(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapCosToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -539,15 +418,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapSin() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.sin(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapSinToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -556,15 +426,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapTan() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.tan(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapTanToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -573,15 +434,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapAcos() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.acos(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapAcosToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -590,15 +442,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapAsin() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.asin(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapAsinToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -607,15 +450,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapAtan() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.atan(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapAtanToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -624,15 +458,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapInv() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = 1.0 / data[i];
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapInvToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -641,15 +466,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapAbs() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.abs(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapAbsToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -658,15 +474,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapSqrt() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.sqrt(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapSqrtToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -675,15 +482,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapCbrt() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.cbrt(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapCbrtToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -692,15 +490,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapCeil() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.ceil(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapCeilToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -709,15 +498,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapFloor() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.floor(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapFloorToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -726,15 +506,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapRint() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.rint(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapRintToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -743,15 +514,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapSignum() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.signum(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapSignumToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -760,15 +522,6 @@ public class ArrayRealVector implements RealVector, Serializable {
return this;
}
- /** {@inheritDoc} */
- public RealVector mapUlp() {
- double[] out = new double[data.length];
- for (int i = 0; i < data.length; i++) {
- out[i] = Math.ulp(data[i]);
- }
- return new ArrayRealVector(out);
- }
-
/** {@inheritDoc} */
public RealVector mapUlpToSelf() {
for (int i = 0; i < data.length; i++) {
@@ -780,15 +533,15 @@ public class ArrayRealVector implements RealVector, Serializable {
/** {@inheritDoc} */
public RealVector ebeMultiply(RealVector v)
throws IllegalArgumentException {
- try {
+ if(v instanceof ArrayRealVector) {
return ebeMultiply((ArrayRealVector) v);
- } catch (ClassCastException cce) {
+ } else {
checkVectorDimensions(v);
- double[] out = new double[data.length];
+ double[] out = data.clone();
for (int i = 0; i < data.length; i++) {
- out[i] = data[i] * v.getEntry(i);
+ out[i] *= v.getEntry(i);
}
- return new ArrayRealVector(out);
+ return new ArrayRealVector(out, false);
}
}
@@ -796,11 +549,11 @@ public class ArrayRealVector implements RealVector, Serializable {
public RealVector ebeMultiply(double[] v)
throws IllegalArgumentException {
checkVectorDimensions(v.length);
- double[] out = new double[data.length];
+ double[] out = data.clone();
for (int i = 0; i < data.length; i++) {
- out[i] = data[i] * v[i];
+ out[i] *= v[i];
}
- return new ArrayRealVector(out);
+ return new ArrayRealVector(out, false);
}
/**
@@ -817,15 +570,15 @@ public class ArrayRealVector implements RealVector, Serializable {
/** {@inheritDoc} */
public RealVector ebeDivide(RealVector v)
throws IllegalArgumentException {
- try {
+ if(v instanceof ArrayRealVector) {
return ebeDivide((ArrayRealVector) v);
- } catch (ClassCastException cce) {
+ } else {
checkVectorDimensions(v);
- double[] out = new double[data.length];
+ double[] out = data.clone();
for (int i = 0; i < data.length; i++) {
- out[i] = data[i] / v.getEntry(i);
+ out[i] /= v.getEntry(i);
}
- return new ArrayRealVector(out);
+ return new ArrayRealVector(out, false);
}
}
@@ -833,11 +586,11 @@ public class ArrayRealVector implements RealVector, Serializable {
public RealVector ebeDivide(double[] v)
throws IllegalArgumentException {
checkVectorDimensions(v.length);
- double[] out = new double[data.length];
+ double[] out = data.clone();
for (int i = 0; i < data.length; i++) {
- out[i] = data[i] / v[i];
+ out[i] /= v[i];
}
- return new ArrayRealVector(out);
+ return new ArrayRealVector(out, false);
}
/**
@@ -868,13 +621,15 @@ public class ArrayRealVector implements RealVector, Serializable {
/** {@inheritDoc} */
public double dotProduct(RealVector v)
throws IllegalArgumentException {
- try {
+ if(v instanceof ArrayRealVector) {
return dotProduct((ArrayRealVector) v);
- } catch (ClassCastException cce) {
+ } else {
checkVectorDimensions(v);
double dot = 0;
- for (int i = 0; i < data.length; i++) {
- dot += data[i] * v.getEntry(i);
+ Iterator it = v.sparseIterator();
+ Entry e;
+ while(it.hasNext() && (e = it.next()) != null) {
+ dot += data[e.getIndex()] * e.getValue();
}
return dot;
}
@@ -932,9 +687,9 @@ public class ArrayRealVector implements RealVector, Serializable {
/** {@inheritDoc} */
public double getDistance(RealVector v)
throws IllegalArgumentException {
- try {
+ if(v instanceof ArrayRealVector) {
return getDistance((ArrayRealVector) v);
- } catch (ClassCastException cce) {
+ } else {
checkVectorDimensions(v);
double sum = 0;
for (int i = 0; i < data.length; ++i) {
@@ -978,9 +733,9 @@ public class ArrayRealVector implements RealVector, Serializable {
/** {@inheritDoc} */
public double getL1Distance(RealVector v)
throws IllegalArgumentException {
- try {
+ if(v instanceof ArrayRealVector) {
return getL1Distance((ArrayRealVector) v);
- } catch (ClassCastException cce) {
+ } else {
checkVectorDimensions(v);
double sum = 0;
for (int i = 0; i < data.length; ++i) {
@@ -1024,9 +779,9 @@ public class ArrayRealVector implements RealVector, Serializable {
/** {@inheritDoc} */
public double getLInfDistance(RealVector v)
throws IllegalArgumentException {
- try {
+ if(v instanceof ArrayRealVector) {
return getLInfDistance((ArrayRealVector) v);
- } catch (ClassCastException cce) {
+ } else {
checkVectorDimensions(v);
double max = 0;
for (int i = 0; i < data.length; ++i) {
@@ -1073,7 +828,7 @@ public class ArrayRealVector implements RealVector, Serializable {
if (norm == 0) {
throw MathRuntimeException.createArithmeticException("zero norm");
}
- return mapDivide(getNorm());
+ return mapDivide(norm);
}
/** {@inheritDoc} */
@@ -1082,9 +837,7 @@ public class ArrayRealVector implements RealVector, Serializable {
if (norm == 0) {
throw MathRuntimeException.createArithmeticException("cannot normalize a zero norm vector");
}
- for (int i = 0; i < data.length; i++) {
- data[i] /= norm;
- }
+ mapDivideToSelf(norm);
}
/** {@inheritDoc} */
@@ -1109,9 +862,9 @@ public class ArrayRealVector implements RealVector, Serializable {
/** {@inheritDoc} */
public RealMatrix outerProduct(RealVector v)
throws IllegalArgumentException {
- try {
+ if(v instanceof ArrayRealVector) {
return outerProduct((ArrayRealVector) v);
- } catch (ClassCastException cce) {
+ } else {
checkVectorDimensions(v);
final int m = data.length;
final RealMatrix out = MatrixUtils.createRealMatrix(m, m);
@@ -1354,33 +1107,26 @@ public class ArrayRealVector implements RealVector, Serializable {
return true;
}
- if (other == null) {
+ if (other == null || !(other instanceof RealVector)) {
return false;
}
- try {
- RealVector rhs = (RealVector) other;
- if (data.length != rhs.getDimension()) {
- return false;
- }
-
- if (rhs.isNaN()) {
- return this.isNaN();
- }
-
- for (int i = 0; i < data.length; ++i) {
- if (data[i] != rhs.getEntry(i)) {
- return false;
- }
- }
- return true;
-
- } catch (ClassCastException ex) {
- // ignore exception
- return false;
+ RealVector rhs = (RealVector) other;
+ if (data.length != rhs.getDimension()) {
+ return false;
}
+ if (rhs.isNaN()) {
+ return this.isNaN();
+ }
+
+ for (int i = 0; i < data.length; ++i) {
+ if (data[i] != rhs.getEntry(i)) {
+ return false;
+ }
+ }
+ return true;
}
/**
@@ -1396,18 +1142,4 @@ public class ArrayRealVector implements RealVector, Serializable {
return MathUtils.hash(data);
}
- /**
- * Check if an index is valid.
- * @param index index to check
- * @exception MatrixIndexException if index is not valid
- */
- private void checkIndex(final int index)
- throws MatrixIndexException {
- if (index < 0 || index >= getDimension()) {
- throw new MatrixIndexException(
- "index {0} out of allowed range [{1}, {2}]",
- index, 0, getDimension() - 1);
- }
- }
-
}
diff --git a/src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java b/src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java
index c404aafda..6052675de 100644
--- a/src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java
+++ b/src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java
@@ -27,7 +27,7 @@ import org.apache.commons.math.util.OpenIntToDoubleHashMap.Iterator;
* @version $Revision$ $Date$
* @since 2.0
*/
-public class OpenMapRealVector implements SparseRealVector, Serializable {
+public class OpenMapRealVector extends AbstractRealVector implements SparseRealVector, Serializable {
/** Default Tolerance for having a value considered zero. */
public static final double DEFAULT_ZERO_TOLERANCE = 1.0e-12;
@@ -41,8 +41,11 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
/** Dimension of the vector. */
private final int virtualSize;
- /** Tolerance for having a value considered zero. */
- private double epsilon;
+ /** Negative tolerance for having a value considered zero. */
+ private double minusEpsilon;
+
+ /** Positive tolerance for having a value considered zero. */
+ private double plusEpsilon;
/**
* Build a 0-length vector.
@@ -54,7 +57,7 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
* into this vector.
*/
public OpenMapRealVector() {
- this(0, DEFAULT_ZERO_TOLERANCE);
+ this(0, DEFAULT_ZERO_TOLERANCE, 0);
}
/**
@@ -62,18 +65,19 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
* @param dimension size of the vector
*/
public OpenMapRealVector(int dimension) {
- this(dimension, DEFAULT_ZERO_TOLERANCE);
+ this(dimension, DEFAULT_ZERO_TOLERANCE, 0);
}
/**
* Construct a (dimension)-length vector of zeros, specifying zero tolerance.
* @param dimension Size of the vector
* @param epsilon The tolerance for having a value considered zero
+ * @param defaultValue value for non-specified entries
*/
- public OpenMapRealVector(int dimension, double epsilon) {
+ public OpenMapRealVector(int dimension, double epsilon, double defaultValue) {
virtualSize = dimension;
- entries = new OpenIntToDoubleHashMap(0.0);
- this.epsilon = epsilon;
+ entries = new OpenIntToDoubleHashMap(defaultValue);
+ setDefault(defaultValue, epsilon);
}
/**
@@ -84,7 +88,8 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
protected OpenMapRealVector(OpenMapRealVector v, int resize) {
virtualSize = v.getDimension() + resize;
entries = new OpenIntToDoubleHashMap(v.entries);
- epsilon = v.getEpsilon();
+ minusEpsilon = v.minusEpsilon;
+ plusEpsilon = v.plusEpsilon;
}
/**
@@ -101,11 +106,12 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
* @param dimension The size of the vector
* @param expectedSize The expected number of non-zero entries
* @param epsilon The tolerance for having a value considered zero
+ * @param defaultValue value for non-specified entries
*/
- public OpenMapRealVector(int dimension, int expectedSize, double epsilon) {
+ public OpenMapRealVector(int dimension, int expectedSize, double epsilon, double defaultValue) {
virtualSize = dimension;
- entries = new OpenIntToDoubleHashMap(expectedSize, 0.0);
- this.epsilon = epsilon;
+ entries = new OpenIntToDoubleHashMap(expectedSize, defaultValue);
+ setDefault(defaultValue, epsilon);
}
/**
@@ -126,10 +132,10 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
public OpenMapRealVector(double[] values, double epsilon) {
virtualSize = values.length;
entries = new OpenIntToDoubleHashMap(0.0);
- this.epsilon = epsilon;
+ setDefault(0, epsilon);
for (int key = 0; key < values.length; key++) {
double value = values[key];
- if (!isZero(value)) {
+ if (!isDefaultValue(value)) {
entries.put(key, value);
}
}
@@ -141,7 +147,7 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
* @param values The set of values to create from
*/
public OpenMapRealVector(Double[] values) {
- this(values, DEFAULT_ZERO_TOLERANCE);
+ this(values, DEFAULT_ZERO_TOLERANCE, 0);
}
/**
@@ -149,14 +155,15 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
* Only non-zero entries will be stored
* @param values The set of values to create from
* @param epsilon The tolerance for having a value considered zero
+ * @param defaultValue value for non-specified entries
*/
- public OpenMapRealVector(Double[] values, double epsilon) {
+ public OpenMapRealVector(Double[] values, double epsilon, double defaultValue) {
virtualSize = values.length;
- entries = new OpenIntToDoubleHashMap(0.0);
- this.epsilon = epsilon;
+ entries = new OpenIntToDoubleHashMap(defaultValue);
+ setDefault(defaultValue, epsilon);
for (int key = 0; key < values.length; key++) {
double value = values[key].doubleValue();
- if (!isZero(value)) {
+ if (!isDefaultValue(value)) {
entries.put(key, value);
}
}
@@ -169,7 +176,8 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
public OpenMapRealVector(OpenMapRealVector v) {
virtualSize = v.getDimension();
entries = new OpenIntToDoubleHashMap(v.getEntries());
- epsilon = v.getEpsilon();
+ plusEpsilon = v.plusEpsilon;
+ minusEpsilon = v.minusEpsilon;
}
/**
@@ -179,15 +187,27 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
public OpenMapRealVector(RealVector v) {
virtualSize = v.getDimension();
entries = new OpenIntToDoubleHashMap(0.0);
- epsilon = DEFAULT_ZERO_TOLERANCE;
+ setDefault(0, DEFAULT_ZERO_TOLERANCE);
for (int key = 0; key < virtualSize; key++) {
double value = v.getEntry(key);
- if (!isZero(value)) {
+ if (!isDefaultValue(value)) {
entries.put(key, value);
}
}
}
+ /** Set defaults.
+ * @param defaultValue value for non-specified entries
+ * @param epsilon tolerance to check for equality with default value
+ */
+ private void setDefault(double defaultValue, double epsilon) {
+ if (epsilon < 0) {
+ throw new IllegalArgumentException("default tolerance must be > 0 :" + epsilon);
+ }
+ plusEpsilon = defaultValue + epsilon;
+ minusEpsilon = defaultValue - epsilon;
+ }
+
/**
* Get the entries of this instance.
* @return entries of this instance
@@ -197,54 +217,41 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
}
/**
- * Determine if this value is zero.
+ * Determine if this value is within epsilon of the defaultValue (currently always zero).
* @param value The value to test
- * @return true
if this value is zero, false
otherwise
+ * @return true
if this value is within epsilon to the defaultValue, false
otherwise
*/
- protected boolean isZero(double value) {
- return value > -epsilon && value < epsilon;
- }
-
- /**
- * Get the tolerance for having a value considered zero.
- * @return The test range for testing if a value is zero
- */
- public double getEpsilon() {
- return epsilon;
- }
-
- /**
- * Set the tolerance for having a value considered zero.
- * @param epsilon The test range for testing if a value is zero
- */
- public void setEpsilon(double epsilon) {
- this.epsilon = epsilon;
+ protected boolean isDefaultValue(double value) {
+ return value < plusEpsilon && value > minusEpsilon;
}
/** {@inheritDoc} */
- public OpenMapRealVector add(RealVector v) throws IllegalArgumentException {
+ public RealVector add(RealVector v) throws IllegalArgumentException {
checkVectorDimensions(v.getDimension());
if (v instanceof OpenMapRealVector) {
return add((OpenMapRealVector) v);
+ } else {
+ return super.add(v);
}
- return add(v.getData());
}
/**
- * Optimized method to add two OpenMapRealVectors.
+ * Optimized method to add two OpenMapRealVectors. Copies the larger vector, iterates over the smaller.
* @param v Vector to add with
* @return The sum of this
with v
* @throws IllegalArgumentException If the dimensions don't match
*/
public OpenMapRealVector add(OpenMapRealVector v) throws IllegalArgumentException{
checkVectorDimensions(v.getDimension());
- OpenMapRealVector res = copy();
- Iterator iter = v.getEntries().iterator();
+ boolean copyThis = entries.size() > v.entries.size();
+ OpenMapRealVector res = copyThis ? this.copy() : v.copy();
+ Iterator iter = copyThis ? v.entries.iterator() : entries.iterator();
+ OpenIntToDoubleHashMap randomAccess = copyThis ? entries : v.entries;
while (iter.hasNext()) {
iter.advance();
int key = iter.key();
- if (entries.containsKey(key)) {
- res.setEntry(key, entries.get(key) + iter.value());
+ if (randomAccess.containsKey(key)) {
+ res.setEntry(key, randomAccess.get(key) + iter.value());
} else {
res.setEntry(key, iter.value());
}
@@ -252,16 +259,6 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
return res;
}
- /** {@inheritDoc} */
- public OpenMapRealVector add(double[] v) throws IllegalArgumentException {
- checkVectorDimensions(v.length);
- OpenMapRealVector res = new OpenMapRealVector(getDimension());
- for (int i = 0; i < v.length; i++) {
- res.setEntry(i, v[i] + getEntry(i));
- }
- return res;
- }
-
/**
* Optimized method to append a OpenMapRealVector.
* @param v vector to append
@@ -306,33 +303,6 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
return new OpenMapRealVector(this);
}
- /** {@inheritDoc} */
- public double dotProduct(RealVector v) throws IllegalArgumentException {
- checkVectorDimensions(v.getDimension());
- double res = 0;
- Iterator iter = entries.iterator();
- while (iter.hasNext()) {
- iter.advance();
- res += v.getEntry(iter.key()) * iter.value();
- }
- return res;
- }
-
- /** {@inheritDoc} */
- public double dotProduct(double[] v) throws IllegalArgumentException {
- checkVectorDimensions(v.length);
- double res = 0;
- Iterator iter = entries.iterator();
- while (iter.hasNext()) {
- int idx = iter.key();
- double value = 0;
- if (idx < v.length) {
- value = v[idx];
- }
- res += value * iter.value();
- }
- return res;
- }
/** {@inheritDoc} */
public OpenMapRealVector ebeDivide(RealVector v) throws IllegalArgumentException {
@@ -1099,7 +1069,7 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
/** {@inheritDoc} */
public void setEntry(int index, double value) throws MatrixIndexException {
checkIndex(index);
- if (!isZero(value)) {
+ if (!isDefaultValue(value)) {
entries.put(index, value);
} else if (entries.containsKey(index)) {
entries.remove(index);
@@ -1185,7 +1155,7 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
/** {@inheritDoc} */
public void unitize() {
double norm = getNorm();
- if (isZero(norm)) {
+ if (isDefaultValue(norm)) {
throw MathRuntimeException.createArithmeticException("cannot normalize a zero norm vector");
}
Iterator iter = entries.iterator();
@@ -1196,37 +1166,6 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
}
- /**
- * Check if an index is valid.
- *
- * @param index
- * index to check
- * @exception MatrixIndexException
- * if index is not valid
- */
- private void checkIndex(final int index) throws MatrixIndexException {
- if (index < 0 || index >= getDimension()) {
- throw new MatrixIndexException(
- "index {0} out of allowed range [{1}, {2}]",
- index, 0, getDimension() - 1);
- }
- }
-
- /**
- * Check if instance dimension is equal to some expected value.
- *
- * @param n
- * expected dimension.
- * @exception IllegalArgumentException
- * if the dimension is inconsistent with vector size
- */
- protected void checkVectorDimensions(int n) throws IllegalArgumentException {
- if (getDimension() != n) {
- throw MathRuntimeException.createIllegalArgumentException(
- "vector length mismatch: got {0} but expected {1}",
- getDimension(), n);
- }
- }
/** {@inheritDoc} */
public double[] toArray() {
@@ -1243,7 +1182,7 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
final int prime = 31;
int result = 1;
long temp;
- temp = Double.doubleToLongBits(epsilon);
+ temp = Double.doubleToLongBits(plusEpsilon) + Double.doubleToLongBits(minusEpsilon);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + virtualSize;
Iterator iter = entries.iterator();
@@ -1276,8 +1215,12 @@ public class OpenMapRealVector implements SparseRealVector, Serializable {
if (virtualSize != other.virtualSize) {
return false;
}
- if (Double.doubleToLongBits(epsilon) !=
- Double.doubleToLongBits(other.epsilon)) {
+ if (Double.doubleToLongBits(minusEpsilon) !=
+ Double.doubleToLongBits(other.minusEpsilon)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(plusEpsilon) !=
+ Double.doubleToLongBits(other.plusEpsilon)) {
return false;
}
Iterator iter = entries.iterator();
diff --git a/src/main/java/org/apache/commons/math/linear/RealVector.java b/src/main/java/org/apache/commons/math/linear/RealVector.java
index 559c788a9..d7145a36c 100644
--- a/src/main/java/org/apache/commons/math/linear/RealVector.java
+++ b/src/main/java/org/apache/commons/math/linear/RealVector.java
@@ -16,6 +16,12 @@
*/
package org.apache.commons.math.linear;
+import java.util.Iterator;
+
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+
+
/**
* Interface defining a real-valued vector with basic algebraic operations.
*
@@ -41,6 +47,74 @@ package org.apache.commons.math.linear;
*/
public interface RealVector {
+ /**
+ * Acts as if it is implemented as:
+ * Entry e = null;
+ * for(Iterator it = iterator(); it.hasNext(); e = it.next()) {
+ * e.setValue(function.value(e.getValue()));
+ * }
+ * @param function to apply to each successive entry
+ * @return this vector
+ * @throws FunctionEvaluationException if function throws it on application to any entry
+ */
+ RealVector mapToSelf(UnivariateRealFunction function) throws FunctionEvaluationException;
+
+ /**
+ * Acts as if implemented as:
+ * return copy().map(function);
+ * @param function to apply to each successive entry
+ * @return a new vector
+ * @throws FunctionEvaluationException if function throws it on application to any entry
+ */
+ RealVector map(UnivariateRealFunction function) throws FunctionEvaluationException;
+
+ /** Class representing a modifiable entry in the vector. */
+ public abstract class Entry {
+
+ /** Index of the entry. */
+ private int index;
+
+ /** Get the value of the entry.
+ * @return value of the entry
+ */
+ public abstract double getValue();
+
+ /** Set the value of the entry.
+ * @param value new value for the entry
+ */
+ public abstract void setValue(double value);
+
+ /** Get the index of the entry.
+ * @return 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;
+ }
+
+ }
+
+ /**
+ * Generic dense iterator - starts with index == zero, and hasNext() == true until index == getDimension();
+ * @return a dense iterator
+ */
+ Iterator iterator();
+
+ /**
+ * Specialized implementations may choose to not iterate over all dimensions, either because those values are
+ * unset, or are equal to defaultValue(), or are small enough to be ignored for the purposes of iteration.
+ * No guarantees are made about order of iteration.
+ * In dense implementations, this method will often delegate to {@see #iterator() }
+ * @return a sparse iterator
+ */
+ Iterator sparseIterator();
+
/**
* Returns a (deep) copy of this.
* @return vector copy
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index ca18f07c4..f64cb18e2 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -39,6 +39,10 @@ The type attribute can be add,update,fix,remove.
+
+ Added mapping and iteration methods to vectors. Provided a default implementation
+ for the numerous simple methods in the RealVectorInterface.
+
Fixed an error in handling very close events in ODE integration.
diff --git a/src/test/java/org/apache/commons/math/linear/AbstractRealVectorTest.java b/src/test/java/org/apache/commons/math/linear/AbstractRealVectorTest.java
new file mode 100644
index 000000000..f5acc9d13
--- /dev/null
+++ b/src/test/java/org/apache/commons/math/linear/AbstractRealVectorTest.java
@@ -0,0 +1,208 @@
+package org.apache.commons.math.linear;
+
+import junit.framework.TestCase;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.linear.RealVector.Entry;
+
+import java.util.Iterator;
+import java.util.Random;
+
+/**
+ *
+ */
+public class AbstractRealVectorTest extends TestCase {
+ private double[] vec1 = { 1d, 2d, 3d, 4d, 5d };
+ private double[] vec2 = { -3d, 0d, 0d, 2d, 1d };
+
+ private static class TestVectorImpl extends AbstractRealVector {
+ private double[] values;
+
+ TestVectorImpl(double[] values) {
+ this.values = values;
+ }
+
+ @Override
+ public double[] getData() { return values; }
+
+ @Override
+ public AbstractRealVector copy() {
+ return new TestVectorImpl(values.clone());
+ }
+
+
+ UnsupportedOperationException unsupported() {
+ return new UnsupportedOperationException("Test implementation only supports methods necessary for testing");
+ }
+
+ public RealVector add(RealVector v) throws IllegalArgumentException {
+ RealVector result = new ArrayRealVector(v);
+ return result.add(this);
+ }
+
+ public RealVector subtract(RealVector v) throws IllegalArgumentException {
+ RealVector result = new ArrayRealVector(v);
+ return result.subtract(this).mapMultiplyToSelf(-1);
+ }
+
+ public RealVector mapAddToSelf(double d) {
+ for(int i=0; i it = v.iterator(); it.hasNext() && (e = it.next()) != null; i++) {
+ assertEquals(vec2[i], e.getValue());
+ }
+ }
+
+ public void testSparseIterator() throws Exception {
+ RealVector v = new TestVectorImpl(vec2.clone());
+ Entry e;
+ int i = 0;
+ double[] nonDefaultV2 = { -3d, 2d, 1d };
+ for(Iterator it = v.sparseIterator(); it.hasNext() && (e = it.next()) != null; i++) {
+ assertEquals(nonDefaultV2[i], e.getValue());
+ }
+ }
+
+ public void testClone() throws Exception {
+ double[] d = new double[1000000];
+ Random r = new Random(1234);
+ for(int i=0;i 0);
+ double[] c = d.clone();
+ c[0] = 1;
+ assertNotSame(c[0], d[0]);
+ d[0] = 1;
+ assertEquals(new ArrayRealVector(d).getNorm(), new ArrayRealVector(c).getNorm());
+ long cloneTime = 0;
+ long setAndAddTime = 0;
+ for(int i=0; i<10; i++) {
+ long start = System.nanoTime();
+ double[] v = d.clone();
+ for(int j=0; j 4) cloneTime += System.nanoTime() - start;
+ start = System.nanoTime();
+ v = new double[d.length];
+ for(int j=0; j 4) setAndAddTime += System.nanoTime() - start;
+ }
+ }
+}
diff --git a/src/test/java/org/apache/commons/math/linear/ArrayRealVectorTest.java b/src/test/java/org/apache/commons/math/linear/ArrayRealVectorTest.java
index 10ffbff83..27ce2591a 100644
--- a/src/test/java/org/apache/commons/math/linear/ArrayRealVectorTest.java
+++ b/src/test/java/org/apache/commons/math/linear/ArrayRealVectorTest.java
@@ -17,12 +17,15 @@
package org.apache.commons.math.linear;
import java.io.Serializable;
+import java.util.Iterator;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
+import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.TestUtils;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
/**
* Test cases for the {@link ArrayRealVector} class.
@@ -63,6 +66,41 @@ public class ArrayRealVectorTest extends TestCase {
return new UnsupportedOperationException("Not supported, unneeded for test purposes");
}
+ public RealVector map(UnivariateRealFunction function) throws FunctionEvaluationException {
+ throw unsupported();
+ }
+
+ public RealVector mapToSelf(UnivariateRealFunction function) throws FunctionEvaluationException {
+ throw unsupported();
+ }
+
+ public Iterator iterator() {
+ return new Iterator() {
+ int i = 0;
+ public boolean hasNext() {
+ return i sparseIterator() {
+ return iterator();
+ }
+
public RealVector copy() {
throw unsupported();
}
diff --git a/src/test/java/org/apache/commons/math/linear/SparseRealVectorTest.java b/src/test/java/org/apache/commons/math/linear/SparseRealVectorTest.java
index b0609d344..1adf25c54 100644
--- a/src/test/java/org/apache/commons/math/linear/SparseRealVectorTest.java
+++ b/src/test/java/org/apache/commons/math/linear/SparseRealVectorTest.java
@@ -17,12 +17,15 @@
package org.apache.commons.math.linear;
import java.io.Serializable;
+import java.util.Iterator;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
+import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.TestUtils;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
/**
* Test cases for the {@link OpenMapRealVector} class.
@@ -63,10 +66,26 @@ public class SparseRealVectorTest extends TestCase {
return new UnsupportedOperationException("Not supported, unneeded for test purposes");
}
- public RealVector copy() {
+ public RealVector map(UnivariateRealFunction function) throws FunctionEvaluationException {
throw unsupported();
}
+ public RealVector mapToSelf(UnivariateRealFunction function) throws FunctionEvaluationException {
+ throw unsupported();
+ }
+
+ public Iterator iterator() {
+ throw unsupported();
+ }
+
+ public Iterator sparseIterator() {
+ throw unsupported();
+ }
+
+ public RealVector copy() {
+ return new SparseRealVectorTestImpl(data);
+ }
+
public RealVector add(RealVector v) throws IllegalArgumentException {
throw unsupported();
}
@@ -432,7 +451,7 @@ public class SparseRealVectorTest extends TestCase {
}
public void setEntry(int index, double value) throws MatrixIndexException {
- throw unsupported();
+ data[index] = value;
}
public void setSubVector(int index, RealVector v) throws MatrixIndexException {