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


Reply via email to