Added mapping and iteration methods to vectors.

Provided a default implementation for the numerous simple methods in the RealVectorInterface.


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@889008 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2009-12-09 22:56:11 +00:00
parent 7fb69bcf38
commit 9e9048ccb5
8 changed files with 1296 additions and 460 deletions

View File

@ -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<Entry> 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<Entry> 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<Entry> 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<Entry> 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<Entry> 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<Entry> 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<Entry> 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<Entry> 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<Entry> 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<Entry> 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<Entry> 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<Entry> 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<Entry> thisIt = sparseIterator();
Entry thisE = null;
while (thisIt.hasNext() && (thisE = thisIt.next()) != null) {
Iterator<Entry> 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<Entry> 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<Entry> sparseIterator() {
return new SparseEntryIterator();
}
/** {@inheritDoc} */
public Iterator<Entry> iterator() {
final int dim = getDimension();
return new Iterator<Entry>() {
/** 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<Entry> 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<Entry> {
/** 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");
}
}
}

View File

@ -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<Entry> 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<Entry> 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<Entry> 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);
}
}
}

View File

@ -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.</p>
*/
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 <code>true</code> if this value is zero, <code>false</code> otherwise
* @return <code>true</code> if this value is within epsilon to the defaultValue, <code>false</code> 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 <code>this</code> with <code>v</code>
* @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();

View File

@ -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.
* <p>
@ -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<Entry> 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<Entry> 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<Entry> sparseIterator();
/**
* Returns a (deep) copy of this.
* @return vector copy

View File

@ -39,6 +39,10 @@ The <action> type attribute can be add,update,fix,remove.
</properties>
<body>
<release version="2.1" date="TBD" description="TBD">
<action dev="luc" type="fix" issue="MATH-312" due-to="Jake Mannix">
Added mapping and iteration methods to vectors. Provided a default implementation
for the numerous simple methods in the RealVectorInterface.
</action>
<action dev="luc" type="fix" issue="MATH-322" >
Fixed an error in handling very close events in ODE integration.
</action>

View File

@ -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<values.length; i++) {
values[i] += d;
}
return this;
}
public RealVector mapSubtractToSelf(double d) {
for(int i=0; i<values.length; i++) {
values[i] -= d;
}
return this;
}
public RealVector mapMultiplyToSelf(double d) {
for(int i=0; i<values.length; i++) {
values[i] *= d;
}
return this;
}
public RealVector mapDivideToSelf(double d) {
for(int i=0; i<values.length; i++) {
values[i] /= d;
}
return this;
}
public RealVector mapPowToSelf(double d) {
for(int i=0; i<values.length; i++) {
values[i] = Math.pow(values[i], d);
}
return this;
}
public RealVector mapInvToSelf() {
for(int i=0; i<values.length; i++) {
values[i] = 1/values[i];
}
return this;
}
public RealVector ebeMultiply(RealVector v) throws IllegalArgumentException {
throw unsupported();
}
public RealVector ebeDivide(RealVector v) throws IllegalArgumentException {
throw unsupported();
}
public double dotProduct(RealVector v) throws IllegalArgumentException {
throw unsupported();
}
public double getNorm() {
throw unsupported();
}
public double getL1Norm() {
throw unsupported();
}
public double getLInfNorm() {
throw unsupported();
}
public RealVector projection(RealVector v) throws IllegalArgumentException {
throw unsupported();
}
public double getEntry(int index) throws MatrixIndexException {
return values[index];
}
public void setEntry(int index, double value) throws MatrixIndexException {
values[index] = value;
}
public int getDimension() {
return values.length;
}
public RealVector append(RealVector v) {
throw unsupported();
}
public RealVector append(double d) {
throw unsupported();
}
public RealVector append(double[] a) {
throw unsupported();
}
public RealVector getSubVector(int index, int n) throws MatrixIndexException {
throw unsupported();
}
public boolean isNaN() {
throw unsupported();
}
public boolean isInfinite() {
throw unsupported();
}
}
private static void assertEquals(double[] d1, double[] d2) {
assertEquals(d1.length, d2.length);
for(int i=0; i<d1.length; i++) assertEquals(d1[i], d2[i]);
}
public void testMap() throws Exception {
double[] vec1Squared = { 1d, 4d, 9d, 16d, 25d };
RealVector v = new TestVectorImpl(vec1.clone());
RealVector w = v.map(new UnivariateRealFunction() { public double value(double x) { return x * x; } });
assertEquals(vec1Squared, w.getData());
}
public void testIterator() throws Exception {
RealVector v = new TestVectorImpl(vec2.clone());
Entry e;
int i = 0;
for(Iterator<Entry> 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<Entry> 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<d.length; i++) d[i] = r.nextDouble();
assertTrue(new ArrayRealVector(d).getNorm() > 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<v.length; j++) v[j] += 1234.5678;
if(i > 4) cloneTime += System.nanoTime() - start;
start = System.nanoTime();
v = new double[d.length];
for(int j=0; j<v.length; j++) v[j] = d[j] + 1234.5678;
if(i > 4) setAndAddTime += System.nanoTime() - start;
}
}
}

View File

@ -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<Entry> iterator() {
return new Iterator<Entry>() {
int i = 0;
public boolean hasNext() {
return i<data.length;
}
public Entry next() {
final int j = i++;
Entry e = new Entry() {
public double getValue() {
return data[j];
}
public void setValue(double newValue) {
data[j] = newValue;
}
};
e.setIndex(j);
return e;
}
public void remove() { }
};
}
public Iterator<Entry> sparseIterator() {
return iterator();
}
public RealVector copy() {
throw unsupported();
}

View File

@ -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<Entry> iterator() {
throw unsupported();
}
public Iterator<Entry> 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 {