From dc4f70a7774aaac3c5e16e2a62bdd11e797fb241 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe Date: Sun, 5 Oct 2008 20:37:15 +0000 Subject: [PATCH] added methods to operate directly on double arrays git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/branches/MATH_2_0@701883 13f79535-47bb-0310-9956-ffa450edef68 --- .../commons/math/linear/RealVector.java | 117 +++++++++ .../commons/math/linear/RealVectorImpl.java | 236 ++++++++++++------ .../math/linear/RealVectorImplTest.java | 52 +++- 3 files changed, 331 insertions(+), 74 deletions(-) diff --git a/src/java/org/apache/commons/math/linear/RealVector.java b/src/java/org/apache/commons/math/linear/RealVector.java index d3718e488..9c449e326 100644 --- a/src/java/org/apache/commons/math/linear/RealVector.java +++ b/src/java/org/apache/commons/math/linear/RealVector.java @@ -56,6 +56,15 @@ public interface RealVector { RealVector add(RealVector v) throws IllegalArgumentException; + /** + * Compute the sum of this and v. + * @param v vector to be added + * @return this + v + * @throws IllegalArgumentException if v is not the same size as this + */ + RealVector add(double[] v) + throws IllegalArgumentException; + /** * Compute this minus v. * @param v vector to be subtracted @@ -65,6 +74,15 @@ public interface RealVector { RealVector subtract(RealVector v) throws IllegalArgumentException; + /** + * Compute this minus v. + * @param v vector to be subtracted + * @return this + v + * @throws IllegalArgumentException if v is not the same size as this + */ + RealVector subtract(double[] v) + throws IllegalArgumentException; + /** * Map an addition operation to each entry. * @param d value to be added to each entry @@ -448,6 +466,15 @@ public interface RealVector { public RealVector ebeMultiply(RealVector v) throws IllegalArgumentException; + /** + * Element-by-element multiplication. + * @param v vector by which instance elements must be multiplied + * @return a vector containing this[i] * v[i] for all i + * @throws IllegalArgumentException if v is not the same size as this + */ + public RealVector ebeMultiply(double[] v) + throws IllegalArgumentException; + /** * Element-by-element division. * @param v vector by which instance elements must be divided @@ -457,6 +484,15 @@ public interface RealVector { public RealVector ebeDivide(RealVector v) throws IllegalArgumentException; + /** + * Element-by-element division. + * @param v vector by which instance elements must be divided + * @return a vector containing this[i] / v[i] for all i + * @throws IllegalArgumentException if v is not the same size as this + */ + public RealVector ebeDivide(double[] v) + throws IllegalArgumentException; + /** * Returns vector entries as a double array. * @return double array of entries @@ -472,6 +508,15 @@ public interface RealVector { double dotProduct(RealVector v) throws IllegalArgumentException; + /** + * Compute the dot product. + * @param v vector with which dot product should be computed + * @return the scalar dot product between instance and v + * @exception IllegalArgumentException if v is not the same size as this + */ + double dotProduct(double[] v) + throws IllegalArgumentException; + /** * Returns the L2 norm of the vector. *

The L2 norm is the root of the sum of @@ -520,6 +565,21 @@ public interface RealVector { double getDistance(RealVector v) throws IllegalArgumentException; + /** + * Distance between two vectors. + *

This method computes the distance consistent with the + * L2 norm, i.e. the square root of the sum of + * elements differences, or euclidian distance.

+ * @param v vector to which distance is requested + * @return distance between two vectors. + * @exception IllegalArgumentException if v is not the same size as this + * @see #getL1Distance(double[]) + * @see #getLInfDistance(double[]) + * @see #getNorm() + */ + double getDistance(double[] v) + throws IllegalArgumentException; + /** * Distance between two vectors. *

This method computes the distance consistent with @@ -535,6 +595,21 @@ public interface RealVector { double getL1Distance(RealVector v) throws IllegalArgumentException; + /** + * Distance between two vectors. + *

This method computes the distance consistent with + * L1 norm, i.e. the sum of the absolute values of + * elements differences.

+ * @param v vector to which distance is requested + * @return distance between two vectors. + * @exception IllegalArgumentException if v is not the same size as this + * @see #getDistance(double[]) + * @see #getLInfDistance(double[]) + * @see #getL1Norm() + */ + double getL1Distance(double[] v) + throws IllegalArgumentException; + /** * Distance between two vectors. *

This method computes the distance consistent with @@ -550,6 +625,21 @@ public interface RealVector { double getLInfDistance(RealVector v) throws IllegalArgumentException; + /** + * Distance between two vectors. + *

This method computes the distance consistent with + * L&infty; norm, i.e. the max of the absolute values of + * elements differences.

+ * @param v vector to which distance is requested + * @return distance between two vectors. + * @exception IllegalArgumentException if v is not the same size as this + * @see #getDistance(double[]) + * @see #getL1Distance(double[]) + * @see #getLInfNorm() + */ + double getLInfDistance(double[] v) + throws IllegalArgumentException; + /** Creates a unit vector pointing in the direction of this vector. *

The instance is not changed by this method.

* @return a unit vector pointing in direction of this vector @@ -571,6 +661,14 @@ public interface RealVector { RealVector projection(RealVector v) throws IllegalArgumentException; + /** Find the orthogonal projection of this vector onto another vector. + * @param v vector onto which instance must be projected + * @return projection of the instance onto v + * @throws IllegalArgumentException if v is not the same size as this + */ + RealVector projection(double[] v) + throws IllegalArgumentException; + /** * Compute the outer product. * @param v vector with which outer product should be computed @@ -580,6 +678,15 @@ public interface RealVector { RealMatrix outerProduct(RealVector v) throws IllegalArgumentException; + /** + * Compute the outer product. + * @param v vector with which outer product should be computed + * @return the square matrix outer product between instance and v + * @exception IllegalArgumentException if v is not the same size as this + */ + RealMatrix outerProduct(double[] v) + throws IllegalArgumentException; + /** * Returns the entry in the specified index. *

@@ -651,6 +758,16 @@ public interface RealVector { void set(int index, RealVector v) throws MatrixIndexException; + /** + * Set a set of consecutive elements. + * @param index index of first element to be set. + * @param v vector containing the values to set. + * @exception MatrixIndexException if the index is + * inconsistent with vector size + */ + void set(int index, double[] v) + throws MatrixIndexException; + /** * Set all elements to a single value. * @param value single value to set for all elements diff --git a/src/java/org/apache/commons/math/linear/RealVectorImpl.java b/src/java/org/apache/commons/math/linear/RealVectorImpl.java index 53d6f7a5b..9700b02c3 100644 --- a/src/java/org/apache/commons/math/linear/RealVectorImpl.java +++ b/src/java/org/apache/commons/math/linear/RealVectorImpl.java @@ -29,7 +29,7 @@ import org.apache.commons.math.util.MathUtils; public class RealVectorImpl implements RealVector, Serializable { /** Serializable version identifier. */ - private static final long serialVersionUID = 7838747548772166404L; + private static final long serialVersionUID = -1097961340710804027L; /** Default format. */ private static final RealVectorFormat DEFAULT_FORMAT = @@ -186,6 +186,39 @@ public class RealVectorImpl implements RealVector, Serializable { System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length); } + /** + * Construct a vector by appending one vector to another vector. + * @param v1 first vector (will be put in front of the new vector) + * @param v2 second vector (will be put at back of the new vector) + */ + public RealVectorImpl(RealVectorImpl v1, double[] v2) { + data = new double[v1.data.length + v2.length]; + System.arraycopy(v1.data, 0, data, 0, v1.data.length); + System.arraycopy(v2, 0, data, v1.data.length, v2.length); + } + + /** + * Construct a vector by appending one vector to another vector. + * @param v1 first vector (will be put in front of the new vector) + * @param v2 second vector (will be put at back of the new vector) + */ + public RealVectorImpl(double[] v1, RealVectorImpl v2) { + data = new double[v1.length + v2.data.length]; + System.arraycopy(v1, 0, data, 0, v1.length); + System.arraycopy(v2.data, 0, data, v1.length, v2.data.length); + } + + /** + * Construct a vector by appending one vector to another vector. + * @param v1 first vector (will be put in front of the new vector) + * @param v2 second vector (will be put at back of the new vector) + */ + public RealVectorImpl(double[] v1, double[] v2) { + data = new double[v1.length + v2.length]; + System.arraycopy(v1, 0, data, 0, v1.length); + System.arraycopy(v2, 0, data, v1.length, v2.length); + } + /** {@inheritDoc} */ public RealVector copy() { return new RealVectorImpl(this, true); @@ -206,6 +239,17 @@ public class RealVectorImpl implements RealVector, Serializable { } } + /** {@inheritDoc} */ + public RealVector add(double[] v) + throws IllegalArgumentException { + checkVectorDimensions(v.length); + double[] out = new double[data.length]; + for (int i = 0; i < data.length; i++) { + out[i] = data[i] + v[i]; + } + return new RealVectorImpl(out); + } + /** * Compute the sum of this and v. * @param v vector to be added @@ -214,12 +258,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public RealVectorImpl add(RealVectorImpl v) throws IllegalArgumentException { - checkVectorDimensions(v); - double[] out = new double[data.length]; - for (int i = 0; i < data.length; i++) { - out[i] = data[i] + v.data[i]; - } - return new RealVectorImpl(out); + return (RealVectorImpl) add(v.data); } /** {@inheritDoc} */ @@ -237,6 +276,17 @@ public class RealVectorImpl implements RealVector, Serializable { } } + /** {@inheritDoc} */ + public RealVector subtract(double[] v) + throws IllegalArgumentException { + checkVectorDimensions(v.length); + double[] out = new double[data.length]; + for (int i = 0; i < data.length; i++) { + out[i] = data[i] - v[i]; + } + return new RealVectorImpl(out); + } + /** * Compute this minus v. * @param v vector to be subtracted @@ -245,12 +295,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public RealVectorImpl subtract(RealVectorImpl v) throws IllegalArgumentException { - checkVectorDimensions(v); - double[] out = new double[data.length]; - for (int i = 0; i < data.length; i++) { - out[i] = data[i] - v.data[i]; - } - return new RealVectorImpl(out); + return (RealVectorImpl) subtract(v.data); } /** {@inheritDoc} */ @@ -744,6 +789,17 @@ public class RealVectorImpl implements RealVector, Serializable { } } + /** {@inheritDoc} */ + public RealVector ebeMultiply(double[] v) + throws IllegalArgumentException { + checkVectorDimensions(v.length); + double[] out = new double[data.length]; + for (int i = 0; i < data.length; i++) { + out[i] = data[i] * v[i]; + } + return new RealVectorImpl(out); + } + /** * Element-by-element multiplication. * @param v vector by which instance elements must be multiplied @@ -752,12 +808,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public RealVectorImpl ebeMultiply(RealVectorImpl v) throws IllegalArgumentException { - checkVectorDimensions(v); - double[] out = new double[data.length]; - for (int i = 0; i < data.length; i++) { - out[i] = data[i] * v.data[i]; - } - return new RealVectorImpl(out); + return (RealVectorImpl) ebeMultiply(v.data); } /** {@inheritDoc} */ @@ -775,6 +826,17 @@ public class RealVectorImpl implements RealVector, Serializable { } } + /** {@inheritDoc} */ + public RealVector ebeDivide(double[] v) + throws IllegalArgumentException { + checkVectorDimensions(v.length); + double[] out = new double[data.length]; + for (int i = 0; i < data.length; i++) { + out[i] = data[i] / v[i]; + } + return new RealVectorImpl(out); + } + /** * Element-by-element division. * @param v vector by which instance elements must be divided @@ -783,12 +845,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public RealVectorImpl ebeDivide(RealVectorImpl v) throws IllegalArgumentException { - checkVectorDimensions(v); - double[] out = new double[data.length]; - for (int i = 0; i < data.length; i++) { - out[i] = data[i] / v.data[i]; - } - return new RealVectorImpl(out); + return (RealVectorImpl) ebeDivide(v.data); } /** {@inheritDoc} */ @@ -820,6 +877,17 @@ public class RealVectorImpl implements RealVector, Serializable { } } + /** {@inheritDoc} */ + public double dotProduct(double[] v) + throws IllegalArgumentException { + checkVectorDimensions(v.length); + double dot = 0; + for (int i = 0; i < data.length; i++) { + dot += data[i] * v[i]; + } + return dot; + } + /** * Compute the dot product. * @param v vector with which dot product should be computed @@ -828,12 +896,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public double dotProduct(RealVectorImpl v) throws IllegalArgumentException { - checkVectorDimensions(v); - double dot = 0; - for (int i = 0; i < data.length; i++) { - dot += data[i] * v.getEntry(i); - } - return dot; + return dotProduct(v.data); } /** {@inheritDoc} */ @@ -879,7 +942,19 @@ public class RealVectorImpl implements RealVector, Serializable { } } - /** + /** {@inheritDoc} */ + public double getDistance(double[] v) + throws IllegalArgumentException { + checkVectorDimensions(v.length); + double sum = 0; + for (int i = 0; i < data.length; ++i) { + final double delta = data[i] - v[i]; + sum += delta * delta; + } + return Math.sqrt(sum); + } + + /** * Distance between two vectors. *

This method computes the distance consistent with the * L2 norm, i.e. the square root of the sum of @@ -894,13 +969,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public double getDistance(RealVectorImpl v) throws IllegalArgumentException { - checkVectorDimensions(v); - double sum = 0; - for (int i = 0; i < data.length; ++i) { - final double delta = data[i] - v.data[i]; - sum += delta * delta; - } - return Math.sqrt(sum); + return getDistance(v.data); } /** {@inheritDoc} */ @@ -919,6 +988,18 @@ public class RealVectorImpl implements RealVector, Serializable { } } + /** {@inheritDoc} */ + public double getL1Distance(double[] v) + throws IllegalArgumentException { + checkVectorDimensions(v.length); + double sum = 0; + for (int i = 0; i < data.length; ++i) { + final double delta = data[i] - v[i]; + sum += Math.abs(delta); + } + return sum; + } + /** * Distance between two vectors. *

This method computes the distance consistent with @@ -934,13 +1015,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public double getL1Distance(RealVectorImpl v) throws IllegalArgumentException { - checkVectorDimensions(v); - double sum = 0; - for (int i = 0; i < data.length; ++i) { - final double delta = data[i] - v.data[i]; - sum += Math.abs(delta); - } - return sum; + return getL1Distance(v.data); } /** {@inheritDoc} */ @@ -959,6 +1034,18 @@ public class RealVectorImpl implements RealVector, Serializable { } } + /** {@inheritDoc} */ + public double getLInfDistance(double[] v) + throws IllegalArgumentException { + checkVectorDimensions(v.length); + double max = 0; + for (int i = 0; i < data.length; ++i) { + final double delta = data[i] - v[i]; + max = Math.max(max, Math.abs(delta)); + } + return max; + } + /** * Distance between two vectors. *

This method computes the distance consistent with @@ -974,13 +1061,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public double getLInfDistance(RealVectorImpl v) throws IllegalArgumentException { - checkVectorDimensions(v); - double max = 0; - for (int i = 0; i < data.length; ++i) { - final double delta = data[i] - v.data[i]; - max = Math.max(max, Math.abs(delta)); - } - return max; + return getLInfDistance(v.data); } /** {@inheritDoc} */ @@ -1008,7 +1089,12 @@ public class RealVectorImpl implements RealVector, Serializable { return v.mapMultiply(dotProduct(v) / v.dotProduct(v)); } - /** Find the orthogonal projection of this vector onto another vector. + /** {@inheritDoc} */ + public RealVector projection(double[] v) { + return projection(new RealVectorImpl(v, false)); + } + + /** Find the orthogonal projection of this vector onto another vector. * @param v vector onto which instance must be projected * @return projection of the instance onto v * @throws IllegalArgumentException if v is not the same size as this @@ -1034,6 +1120,19 @@ public class RealVectorImpl implements RealVector, Serializable { } } + /** {@inheritDoc} */ + public RealMatrix outerProduct(double[] v) + throws IllegalArgumentException { + checkVectorDimensions(v.length); + double[][] out = new double[data.length][data.length]; + for (int i = 0; i < data.length; i++) { + for (int j = 0; j < data.length; j++) { + out[i][j] = data[i] * v[j]; + } + } + return new RealMatrixImpl(out); + } + /** * Compute the outer product. * @param v vector with which outer product should be computed @@ -1042,14 +1141,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public RealMatrixImpl outerProduct(RealVectorImpl v) throws IllegalArgumentException { - checkVectorDimensions(v); - double[][] out = new double[data.length][data.length]; - for (int i = 0; i < data.length; i++) { - for (int j = 0; j < data.length; j++) { - out[i][j] = data[i] * v.data[j]; - } - } - return new RealMatrixImpl(out); + return (RealMatrixImpl) outerProduct(v.data); } /** {@inheritDoc} */ @@ -1090,10 +1182,7 @@ public class RealVectorImpl implements RealVector, Serializable { /** {@inheritDoc} */ public RealVector append(double[] in) { - final double[] out = new double[data.length + in.length]; - System.arraycopy(data, 0, out, 0, data.length); - System.arraycopy(in, 0, out, data.length, in.length); - return new RealVectorImpl(out); + return new RealVectorImpl(this, in); } /** {@inheritDoc} */ @@ -1132,6 +1221,15 @@ public class RealVectorImpl implements RealVector, Serializable { } } + /** {@inheritDoc} */ + public void set(int index, double[] v) { + try { + System.arraycopy(v, 0, data, index, v.length); + } catch (IndexOutOfBoundsException e) { + throw new MatrixIndexException(e.getMessage()); + } + } + /** * Set a set of consecutive elements. * @@ -1142,11 +1240,7 @@ public class RealVectorImpl implements RealVector, Serializable { */ public void set(int index, RealVectorImpl v) throws MatrixIndexException { - try { - System.arraycopy(v.data, 0, data, index, v.data.length); - } catch (IndexOutOfBoundsException e) { - throw new MatrixIndexException(e.getMessage()); - } + set(index, v.data); } /** {@inheritDoc} */ diff --git a/src/test/org/apache/commons/math/linear/RealVectorImplTest.java b/src/test/org/apache/commons/math/linear/RealVectorImplTest.java index 581aa98b5..baf2993d2 100644 --- a/src/test/org/apache/commons/math/linear/RealVectorImplTest.java +++ b/src/test/org/apache/commons/math/linear/RealVectorImplTest.java @@ -47,7 +47,7 @@ public class RealVectorImplTest extends TestCase { public static class RealVectorTestImpl implements RealVector, Serializable { /** Serializable version identifier. */ - private static final long serialVersionUID = 8731816072271374422L; + private static final long serialVersionUID = 4715341047369582908L; /** Entries of the vector. */ protected double data[]; @@ -68,10 +68,18 @@ public class RealVectorImplTest extends TestCase { throw unsupported(); } + public RealVector add(double[] v) throws IllegalArgumentException { + throw unsupported(); + } + public RealVector subtract(RealVector v) throws IllegalArgumentException { throw unsupported(); } + public RealVector subtract(double[] v) throws IllegalArgumentException { + throw unsupported(); + } + public RealVector mapAdd(double d) { throw unsupported(); } @@ -304,17 +312,23 @@ public class RealVectorImplTest extends TestCase { throw unsupported(); } + public RealVector ebeMultiply(double[] v) throws IllegalArgumentException { + throw unsupported(); + } + public RealVector ebeDivide(RealVector v) throws IllegalArgumentException { throw unsupported(); } + public RealVector ebeDivide(double[] v) throws IllegalArgumentException { + throw unsupported(); + } + public double[] getData() { return data.clone(); } public double dotProduct(RealVector v) throws IllegalArgumentException { - - // checkVectorDimensions(v); double dot = 0; for (int i = 0; i < data.length; i++) { dot += data[i] * v.getEntry(i); @@ -322,6 +336,14 @@ public class RealVectorImplTest extends TestCase { return dot; } + public double dotProduct(double[] v) throws IllegalArgumentException { + double dot = 0; + for (int i = 0; i < data.length; i++) { + dot += data[i] * v[i]; + } + return dot; + } + public double getNorm() { throw unsupported(); } @@ -338,14 +360,26 @@ public class RealVectorImplTest extends TestCase { throw unsupported(); } + public double getDistance(double[] v) throws IllegalArgumentException { + throw unsupported(); + } + public double getL1Distance(RealVector v) throws IllegalArgumentException { throw unsupported(); } + public double getL1Distance(double[] v) throws IllegalArgumentException { + throw unsupported(); + } + public double getLInfDistance(RealVector v) throws IllegalArgumentException { throw unsupported(); } + public double getLInfDistance(double[] v) throws IllegalArgumentException { + throw unsupported(); + } + public RealVector unitVector() { throw unsupported(); } @@ -358,10 +392,18 @@ public class RealVectorImplTest extends TestCase { throw unsupported(); } + public RealVector projection(double[] v) throws IllegalArgumentException { + throw unsupported(); + } + public RealMatrix outerProduct(RealVector v) throws IllegalArgumentException { throw unsupported(); } + public RealMatrix outerProduct(double[] v) throws IllegalArgumentException { + throw unsupported(); + } + public double getEntry(int index) throws MatrixIndexException { return data[index]; } @@ -394,6 +436,10 @@ public class RealVectorImplTest extends TestCase { throw unsupported(); } + public void set(int index, double[] v) throws MatrixIndexException { + throw unsupported(); + } + public void set(double value) { throw unsupported(); }