Author: erans
Date: Wed Aug 24 12:15:51 2011
New Revision: 1161064
URL: http://svn.apache.org/viewvc?rev=1161064&view=rev
Log:
MATH-646
Unmodifiable view of a vector.
Added:
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableArrayRealVectorTest.java
(with props)
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableOpenMapRealVectorTest.java
(with props)
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableRealVectorAbstractTest.java
(with props)
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java?rev=1161064&r1=1161063&r2=1161064&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
Wed Aug 24 12:15:51 2011
@@ -631,4 +631,391 @@ public abstract class AbstractRealVector
throw new MathUnsupportedOperationException();
}
}
+
+ /**
+ * This class is an implementation of {@link RealVector} with read-only
+ * access.
+ * It wraps any {@link RealVector}, and exposes all methods which do not
+ * modify it. Invoking methods which should normally result in the
+ * modification of the calling {@link RealVector} results in an
+ * {@link MathUnsupportedOperationException}. It should be noted that
+ * {@link UnmodifiableVector} is <em>not</em> immutable.
+ */
+ private static final class UnmodifiableVector implements RealVector {
+ /** The vector for which an unmodifiable view is provided. */
+ private final RealVector v;
+
+ /**
+ * Creates a view of the given vector.
+ *
+ * @param v Vector wrapped in {@code this} view.
+ */
+ public UnmodifiableVector(RealVector v) {
+ this.v = v;
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapToSelf(UnivariateRealFunction function) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector map(UnivariateRealFunction function) {
+ return v.map(function);
+ }
+
+ /** {@inheritDoc} */
+ public Iterator<Entry> iterator() {
+ final Iterator<Entry> i = v.iterator();
+ return new Iterator<Entry>() {
+ /** The current entry. */
+ private final UnmodifiableEntry e = new UnmodifiableEntry();
+
+ public boolean hasNext() {
+ return i.hasNext();
+ }
+
+ public Entry next() {
+ e.setIndex(i.next().getIndex());
+ return e;
+ }
+
+ public void remove() {
+ throw new MathUnsupportedOperationException();
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
+ public Iterator<Entry> sparseIterator() {
+ final Iterator<Entry> i = v.sparseIterator();
+ return new Iterator<Entry>() {
+ /** The current entry. */
+ private final UnmodifiableEntry e = new UnmodifiableEntry();
+
+ public boolean hasNext() {
+ return i.hasNext();
+ }
+
+ public Entry next() {
+ e.setIndex(i.next().getIndex());
+ return e;
+ }
+
+ public void remove() {
+ throw new MathUnsupportedOperationException();
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
+ public RealVector copy() {
+ return v.copy();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector add(RealVector w) {
+ return v.add(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector add(double[] w) {
+ return v.add(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector subtract(RealVector w) {
+ return v.subtract(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector subtract(double[] w) {
+ return v.subtract(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAdd(double d) {
+ return v.mapAdd(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapAddToSelf(double d) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSubtract(double d) {
+ return v.mapSubtract(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapSubtractToSelf(double d) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapMultiply(double d) {
+ return v.mapMultiply(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapMultiplyToSelf(double d) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapDivide(double d) {
+ return v.mapDivide(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector mapDivideToSelf(double d) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector ebeMultiply(RealVector w) {
+ return v.ebeMultiply(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector ebeMultiply(double[] w) {
+ return v.ebeMultiply(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector ebeDivide(RealVector w) {
+ return v.ebeDivide(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector ebeDivide(double[] w) {
+ return v.ebeDivide(w);
+ }
+
+ /** {@inheritDoc} */
+ public double[] getData() {
+ // TODO It is not specified in the javadoc that getData should
+ // return a
+ // deep copy
+ return v.getData();
+ }
+
+ /** {@inheritDoc} */
+ public double dotProduct(RealVector w) {
+ return v.dotProduct(w);
+ }
+
+ /** {@inheritDoc} */
+ public double dotProduct(double[] w) {
+ return v.dotProduct(w);
+ }
+
+ /** {@inheritDoc} */
+ public double cosine(RealVector w) {
+ return v.cosine(w);
+ }
+
+ /** {@inheritDoc} */
+ public double cosine(double[] w) {
+ return v.cosine(w);
+ }
+
+ /** {@inheritDoc} */
+ public double getNorm() {
+ return v.getNorm();
+ }
+
+ /** {@inheritDoc} */
+ public double getL1Norm() {
+ return v.getL1Norm();
+ }
+
+ /** {@inheritDoc} */
+ public double getLInfNorm() {
+ return v.getLInfNorm();
+ }
+
+ /** {@inheritDoc} */
+ public double getDistance(RealVector w) {
+ return v.getDistance(w);
+ }
+
+ /** {@inheritDoc} */
+ public double getDistance(double[] w) {
+ return v.getDistance(w);
+ }
+
+ /** {@inheritDoc} */
+ public double getL1Distance(RealVector w) {
+ return v.getL1Distance(w);
+ }
+
+ /** {@inheritDoc} */
+ public double getL1Distance(double[] w) {
+ return v.getL1Distance(w);
+ }
+
+ /** {@inheritDoc} */
+ public double getLInfDistance(RealVector w) {
+ return v.getLInfDistance(w);
+ }
+
+ /** {@inheritDoc} */
+ public double getLInfDistance(double[] w) {
+ return v.getLInfDistance(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector unitVector() {
+ return v.unitVector();
+ }
+
+ /** {@inheritDoc} */
+ public void unitize() {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector projection(RealVector w) {
+ return v.projection(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector projection(double[] w) {
+ return v.projection(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealMatrix outerProduct(RealVector w) {
+ return v.outerProduct(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealMatrix outerProduct(double[] w) {
+ return v.outerProduct(w);
+ }
+
+ /** {@inheritDoc} */
+ public double getEntry(int index) {
+ return v.getEntry(index);
+ }
+
+ /** {@inheritDoc} */
+ public void setEntry(int index, double value) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public int getDimension() {
+ return v.getDimension();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector append(RealVector w) {
+ return v.append(w);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector append(double d) {
+ return v.append(d);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector append(double[] a) {
+ return v.append(a);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector getSubVector(int index, int n) {
+ return v.getSubVector(index, n);
+ }
+
+ /** {@inheritDoc} */
+ public void setSubVector(int index, RealVector w) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public void setSubVector(int index, double[] w) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public void set(double value) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public double[] toArray() {
+ return v.toArray();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isNaN() {
+ return v.isNaN();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isInfinite() {
+ return v.isInfinite();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector combine(double a, double b, double[] y) {
+ return v.combine(a, b, y);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector combine(double a, double b, RealVector y) {
+ return v.combine(a, b, y);
+ }
+
+ /** {@inheritDoc} */
+ public RealVector combineToSelf(double a, double b, double[] y) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public RealVector combineToSelf(double a, double b, RealVector y) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /** An entry in the vector. */
+ private class UnmodifiableEntry extends Entry {
+ /** {@inheritDoc} */
+ @Override
+ public double getValue() {
+ return v.getEntry(getIndex());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setValue(double newValue) {
+ throw new MathUnsupportedOperationException();
+ }
+ }
+ }
+
+ /**
+ * Returns an unmodifiable view of the specified vector.
+ * The returned vector has read-only access. An attempt to modify it will
+ * result in a {@link MathUnsupportedOperationException}. However, the
+ * returned vector is <em>not</em> immutable, since any modification of
+ * {@code v} will also change the returned view.
+ * For example, in the following piece of code
+ * <pre>
+ * RealVector v = new ArrayRealVector(2);
+ * RealVector w = RealVector.unmodifiableRealVector(v);
+ * v.setEntry(0, 1.2);
+ * v.setEntry(1, -3.4);
+ * </pre>
+ * the changes will be seen in the {@code w} view of {@code v}.
+ *
+ * @param v Vector for which an unmodifiable view is to be returned.
+ * @return an unmodifiable view of {@code v}.
+ */
+ public static RealVector unmodifiableRealVector(final RealVector v) {
+ return new UnmodifiableVector(v);
+ }
}
Added:
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableArrayRealVectorTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableArrayRealVectorTest.java?rev=1161064&view=auto
==============================================================================
---
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableArrayRealVectorTest.java
(added)
+++
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableArrayRealVectorTest.java
Wed Aug 24 12:15:51 2011
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+/**
+ * This is an implementation of {@link UnmodifiableRealVectorAbstractTest} for
+ * unmodifiable views of {@link ArrayRealVectorTest}.
+ *
+ * @version $Id$
+ */
+public class UnmodifiableArrayRealVectorTest
+ extends UnmodifiableRealVectorAbstractTest {
+ /**
+ * Returns a random vector of type {@link ArrayRealVector}.
+ *
+ * @return a new random {@link ArrayRealVector}.
+ */
+ @Override
+ public RealVector createVector() {
+ ArrayRealVector v = new ArrayRealVector(DIM);
+ for (int i = 0; i < DIM; i++) {
+ v.setEntry(i, RANDOM.nextDouble());
+ }
+ return v;
+ }
+}
Propchange:
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableArrayRealVectorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableOpenMapRealVectorTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableOpenMapRealVectorTest.java?rev=1161064&view=auto
==============================================================================
---
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableOpenMapRealVectorTest.java
(added)
+++
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableOpenMapRealVectorTest.java
Wed Aug 24 12:15:51 2011
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+/**
+ * This is an implementation of {@link UnmodifiableRealVectorAbstractTest} for
+ * unmodifiable views of {@link OpenMapRealVector}.
+ *
+ * @version $Id$
+ */
+public class UnmodifiableOpenMapRealVectorTest
+ extends UnmodifiableRealVectorAbstractTest {
+ /** To ensure sufficient sparsity. */
+ public static final double PROBABILITY_OF_ZERO = 0.5;
+
+ /**
+ * Returns a random vector of type {@link ArrayRealVector}.
+ *
+ * @return a new random {@link ArrayRealVector}.
+ */
+ @Override
+ public RealVector createVector() {
+ OpenMapRealVector v = new OpenMapRealVector(DIM, EPS);
+ for (int i = 0; i < DIM; i++) {
+ if (RANDOM.nextDouble() > PROBABILITY_OF_ZERO) {
+ v.setEntry(i, RANDOM.nextDouble());
+ }
+ }
+ return v;
+ }
+}
Propchange:
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableOpenMapRealVectorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableRealVectorAbstractTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableRealVectorAbstractTest.java?rev=1161064&view=auto
==============================================================================
---
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableRealVectorAbstractTest.java
(added)
+++
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableRealVectorAbstractTest.java
Wed Aug 24 12:15:51 2011
@@ -0,0 +1,431 @@
+/*
+ * 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.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Random;
+
+import junit.framework.Assert;
+
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.analysis.function.Sin;
+import org.apache.commons.math.exception.MathUnsupportedOperationException;
+import org.apache.commons.math.linear.RealVector.Entry;
+import org.junit.Test;
+
+/**
+ * This is an abstract test of the {@link
AbstractRealVector.UnmodifiableVector}
+ * implementation. These unmodifiable vectors decorate a (modifiable)
+ * {@link RealVector}; therefore, a new implementation of this abstract test
+ * should be considered for each implementation of {@link RealVector}.
+ *
+ * @version $Id$
+ *
+ */
+public abstract class UnmodifiableRealVectorAbstractTest {
+ /** The dimension of the randomly generated vectors. */
+ protected static final int DIM = 100;
+ /** Absolute tolerance. */
+ protected static final double EPS = 10 * Math.ulp(1d);
+ /**
+ * The list of methods which are excluded from the general test
+ * {@link #testAllButExcluded()}.
+ */
+ protected static final ArrayList<String> EXCLUDE;
+ /** The random number generator (always initialized with the same seed. */
+ protected static final Random RANDOM;
+
+ static {
+ EXCLUDE = new ArrayList<String>();
+ EXCLUDE.add("getEntry");
+ EXCLUDE.add("setEntry");
+ EXCLUDE.add("getSubVector");
+ EXCLUDE.add("setSubVector");
+ EXCLUDE.add("iterator");
+ EXCLUDE.add("sparseIterator");
+ RANDOM = new Random(20110813);
+ }
+
+ /**
+ * Returns {@code true} if the specified {@code double} are equal (within a
+ * given tolerance).
+ *
+ * @param x First {@code double}.
+ * @param y Second {@code double}.
+ * @return {@code true} if {@code x} and {@code y} are equal.
+ */
+ public static boolean equals(final double x, final double y) {
+ if (x == y) {
+ return true;
+ } else if (Math.abs(x) <= EPS) {
+ return Math.abs(y) <= EPS;
+ } else if (Math.abs(y) <= EPS) {
+ return Math.abs(x) <= EPS;
+ } else {
+ return Math.abs(x - y) <= EPS * Math.min(Math.abs(x), Math.abs(y));
+ }
+ }
+
+ /**
+ * Returns {@code true} if the specified {@code double} arrays are equal
+ * (within a given tolerance).
+ *
+ * @param x First array.
+ * @param y Second array.
+ * @return {@code true} if {@code x} and {@code y} are equal.
+ */
+ public static boolean equals(final double[] x, final double[] y) {
+ if (x.length != y.length) {
+ return false;
+ }
+ final int n = x.length;
+ for (int i = 0; i < n; i++) {
+ if (!equals(x[i], y[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the specified {@code RealVector} are equal
+ * (within a given tolerance).
+ *
+ * @param x First vector.
+ * @param y Second vector.
+ * @return {@code true} if {@code x} and {@code y} are equal.
+ */
+ public static boolean equals(final RealVector x, final RealVector y) {
+ if (x.getDimension() != y.getDimension()) {
+ return false;
+ }
+ final int n = x.getDimension();
+ for (int i = 0; i < n; i++) {
+ if (!equals(x.getEntry(i), y.getEntry(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the specified {@code RealVector} is equal to the
+ * specified {@code double} array (within a given tolerance).
+ *
+ * @param x Vector.
+ * @param y Array.
+ * @return {@code true} if {@code x} and {@code y} are equal.
+ */
+ public static boolean equals(final RealVector x, final double[] y) {
+ if (x.getDimension() != y.length) {
+ return false;
+ }
+ final int n = x.getDimension();
+ for (int i = 0; i < n; i++) {
+ if (!equals(x.getEntry(i), y[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the specified {@code RealMatrix} are equal
+ * (within a given tolerance).
+ *
+ * @param x First matrix.
+ * @param y Second matrix.
+ * @return {@code true} if {@code x} and {@code y} are equal.
+ */
+ public static boolean equals(final RealMatrix x, final RealMatrix y) {
+ if (x.getRowDimension() != y.getRowDimension()) {
+ return false;
+ }
+ if (x.getColumnDimension() != y.getColumnDimension()) {
+ return false;
+ }
+ final int rows = x.getRowDimension();
+ final int cols = x.getColumnDimension();
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < cols; j++) {
+ if (!equals(x.getEntry(i, j), y.getEntry(i, j))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the specified {@code Object} are equal.
+ *
+ * @param x First object.
+ * @param y Second object.
+ * @return {@code true} if {@code x} and {@code y} are equal.
+ * @throws IllegalArgumentException if {@code x} and {@code y} could
+ * not be compared.
+ */
+ public static boolean equals(final Object x, final Object y) {
+ if (x instanceof Boolean) {
+ if (y instanceof Boolean) {
+ return ((Boolean) x).booleanValue() == ((Boolean) y)
+ .booleanValue();
+ } else {
+ return false;
+ }
+ }
+ if (x instanceof Integer) {
+ if (y instanceof Integer) {
+ return ((Integer) x).intValue() == ((Integer) y).intValue();
+ } else {
+ return false;
+ }
+ } else if (x instanceof Double) {
+ if (y instanceof Double) {
+ return equals(((Double) x).doubleValue(),
+ ((Double) y).doubleValue());
+ } else {
+ return false;
+ }
+ } else if (x instanceof double[]) {
+ if (y instanceof double[]) {
+ return equals((double[]) x, (double[]) y);
+ } else if (y instanceof RealVector) {
+ return equals((RealVector) y, (double[]) x);
+ } else {
+ return false;
+ }
+ } else if (x instanceof RealVector) {
+ if (y instanceof double[]) {
+ return equals((RealVector) x, (double[]) y);
+ } else if (y instanceof RealVector) {
+ return equals((RealVector) x, (RealVector) y);
+ } else {
+ return false;
+ }
+ } else if (x instanceof RealMatrix) {
+ if (y instanceof RealMatrix) {
+ return equals((RealMatrix) x, (RealMatrix) y);
+ } else {
+ return false;
+ }
+ } else {
+ throw new IllegalArgumentException("could not compare " + x + ", "
+ + y);
+ }
+ }
+
+ /**
+ * Creates a new random vector of a specified type. This vector is then to
+ * be wrapped in a {@link AbstractRealVector.UnmodifiableVector}.
+ *
+ * @return a new random vector.
+ */
+ public abstract RealVector createVector();
+
+ /**
+ * Creates a new random object of the specified type.
+ *
+ * @param c
+ * the class of the object to be created.
+ * @return a new random object.
+ * @throws IllegalArgumentException
+ * if the specified class is not recognized by this method.
+ */
+ public Object createParameter(final Class<?> c) {
+ if (c == Integer.TYPE) {
+ return Integer.valueOf(RANDOM.nextInt());
+ } else if (c == Double.TYPE) {
+ return Double.valueOf(RANDOM.nextDouble());
+ } else if (c == double[].class) {
+ final double[] v = new double[DIM];
+ for (int i = 0; i < DIM; i++) {
+ v[i] = RANDOM.nextDouble();
+ }
+ return v;
+ } else if (c.isAssignableFrom(RealVector.class)) {
+ return createVector();
+ } else if (c.isAssignableFrom(UnivariateRealFunction.class)) {
+ return new Sin();
+ } else {
+ throw new IllegalArgumentException("could not create " + c);
+ }
+ }
+
+ /**
+ * This is the general test of most methods in
+ * {@link AbstractRealVector.UnmodifiableVector}. It works as follows.
+ * First, an unmodifiable view of a copy of the specified random vector
+ * {@code u} is created: this defines {@code v}. Then the <em>same</em>
+ * method {@code m} is invoked on {@code u} and {@code v}, with randomly
+ * generated parameters {@code args}.
+ * If it turns out that {@code u} has changed after the call of method
+ * {@code m}, then this test checks that the call of this method on
+ * {@code v} resulted in a {@link MathUnsupportedOperationException}. If
+ * {@code u} was not modified, then this test checks that the results
+ * returned by the call of method {@code m} on {@code u} and {@code v}
+ * returned the same result.
+ *
+ * @param m Method to be tested.
+ * @param u Random vector from which the unmodifiable view is to be
+ *constructed.
+ * @param args Arguments to be passed to method {@code m}.
+ */
+ private void callMethod(final Method m, final RealVector u,
+ final Object... args) throws IllegalAccessException,
+ IllegalArgumentException, InvocationTargetException {
+ final RealVector uu = u.copy();
+ final RealVector v = AbstractRealVector
+ .unmodifiableRealVector(u.copy());
+ Object exp = m.invoke(u, args);
+ if (equals(uu, u)) {
+ Object act = m.invoke(v, args);
+ Assert.assertTrue(m.toGenericString()
+ + ", unmodifiable vector has changed", equals(uu, v));
+ Assert.assertTrue(m.toGenericString() + ", wrong result",
+ equals(exp, act));
+
+ } else {
+ boolean flag = false;
+ try {
+ m.invoke(v, args);
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof MathUnsupportedOperationException)
{
+ flag = true;
+ }
+ }
+ Assert.assertTrue(m.toGenericString()+", exception should have
been thrown", flag);
+ }
+ }
+
+ /**
+ * This test calls {@link #callMethod(Method, RealVector, Object...)} on
+ * every method defined in interface {@link RealVector}. It generates the
+ * appropriate random arguments. Some methods are manually excluded (see
+ * {@link #EXCLUDE}), they must be handled by separate tests.
+ */
+ @Test
+ public void testAllButExcluded() throws IllegalAccessException,
+ IllegalArgumentException, InvocationTargetException {
+ Method[] method = RealVector.class.getMethods();
+ for (int i = 0; i < method.length; i++) {
+ Method m = method[i];
+ if (!EXCLUDE.contains(m.getName())) {
+ RealVector u = (RealVector) createParameter(RealVector.class);
+ Class<?>[] paramType = m.getParameterTypes();
+ Object[] param = new Object[paramType.length];
+ for (int j = 0; j < paramType.length; j++) {
+ param[j] = createParameter(paramType[j]);
+ }
+ callMethod(m, u, param);
+ }
+ }
+ }
+
+ @Test
+ public void testGetEntry() {
+ RealVector u = createVector();
+ RealVector v = AbstractRealVector.unmodifiableRealVector(u);
+ for (int i = 0; i < DIM; i++) {
+ Assert.assertTrue(equals(u.getEntry(i), v.getEntry(i)));
+ }
+ }
+
+ @Test(expected = MathUnsupportedOperationException.class)
+ public void testSetEntry() {
+ RealVector u = createVector();
+ RealVector v = AbstractRealVector.unmodifiableRealVector(u);
+ for (int i = 0; i < DIM; i++) {
+ v.setEntry(i, 0d);
+ }
+ }
+
+ @Test
+ public void testGetSubVector() {
+ RealVector u = createVector();
+ RealVector v = AbstractRealVector.unmodifiableRealVector(u);
+ for (int i = 0; i < DIM; i++) {
+ for (int n = 1; n < DIM - i; n++) {
+ RealVector exp = u.getSubVector(i, n);
+ RealVector act = v.getSubVector(i, n);
+ Assert.assertTrue(equals(exp, act));
+ }
+ }
+ }
+
+ @Test(expected = MathUnsupportedOperationException.class)
+ public void testSetSubVector() {
+ RealVector u = createVector();
+ RealVector v = AbstractRealVector.unmodifiableRealVector(u);
+ v.setSubVector(0, new ArrayRealVector());
+ }
+
+ @Test
+ public void testIterator() {
+ RealVector u = createVector();
+ Iterator<Entry> i = u.iterator();
+ RealVector v = AbstractRealVector.unmodifiableRealVector(u.copy());
+ Iterator<Entry> j = v.iterator();
+ boolean flag;
+ while (i.hasNext()) {
+ Assert.assertTrue(j.hasNext());
+ Entry exp = i.next();
+ Entry act = j.next();
+ Assert.assertTrue(equals(exp.getIndex(), act.getIndex()));
+ Assert.assertTrue(equals(exp.getValue(), act.getValue()));
+ exp.setIndex(RANDOM.nextInt(DIM));
+ act.setIndex(RANDOM.nextInt(DIM));
+ flag = false;
+ try {
+ act.setValue(RANDOM.nextDouble());
+ } catch (MathUnsupportedOperationException e) {
+ flag = true;
+ }
+ Assert.assertTrue("exception should have been thrown", flag);
+ }
+ Assert.assertFalse(j.hasNext());
+ }
+
+ @Test
+ public void testSparseIterator() {
+ RealVector u = createVector();
+ Iterator<Entry> i = u.sparseIterator();
+ RealVector v = AbstractRealVector.unmodifiableRealVector(u.copy());
+ Iterator<Entry> j = v.sparseIterator();
+ boolean flag;
+ while (i.hasNext()) {
+ Assert.assertTrue(j.hasNext());
+ Entry exp = i.next();
+ Entry act = j.next();
+ Assert.assertTrue(equals(exp.getIndex(), act.getIndex()));
+ Assert.assertTrue(equals(exp.getValue(), act.getValue()));
+ exp.setIndex(RANDOM.nextInt(DIM));
+ act.setIndex(RANDOM.nextInt(DIM));
+ flag = false;
+ try {
+ act.setValue(RANDOM.nextDouble());
+ } catch (MathUnsupportedOperationException e) {
+ flag = true;
+ }
+ Assert.assertTrue("exception should have been thrown", flag);
+ }
+ Assert.assertFalse(j.hasNext());
+ }
+}
Propchange:
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/UnmodifiableRealVectorAbstractTest.java
------------------------------------------------------------------------------
svn:eol-style = native