Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id BF3E48FD3 for ; Wed, 24 Aug 2011 12:16:21 +0000 (UTC) Received: (qmail 15084 invoked by uid 500); 24 Aug 2011 12:16:21 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 14741 invoked by uid 500); 24 Aug 2011 12:16:16 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 14734 invoked by uid 99); 24 Aug 2011 12:16:15 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 24 Aug 2011 12:16:15 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 24 Aug 2011 12:16:12 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 6D7CD23889E5 for ; Wed, 24 Aug 2011 12:15:52 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1161064 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math/linear/ test/java/org/apache/commons/math/linear/ Date: Wed, 24 Aug 2011 12:15:52 -0000 To: commits@commons.apache.org From: erans@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110824121552.6D7CD23889E5@eris.apache.org> 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 not 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 iterator() { + final Iterator i = v.iterator(); + return new Iterator() { + /** 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 sparseIterator() { + final Iterator i = v.sparseIterator(); + return new Iterator() { + /** 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 not immutable, since any modification of + * {@code v} will also change the returned view. + * For example, in the following piece of code + *
+     *     RealVector v = new ArrayRealVector(2);
+     *     RealVector w = RealVector.unmodifiableRealVector(v);
+     *     v.setEntry(0, 1.2);
+     *     v.setEntry(1, -3.4);
+     * 
+ * 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 EXCLUDE; + /** The random number generator (always initialized with the same seed. */ + protected static final Random RANDOM; + + static { + EXCLUDE = new ArrayList(); + 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 same + * 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 i = u.iterator(); + RealVector v = AbstractRealVector.unmodifiableRealVector(u.copy()); + Iterator 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 i = u.sparseIterator(); + RealVector v = AbstractRealVector.unmodifiableRealVector(u.copy()); + Iterator 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