Author: celestin Date: Mon May 28 08:31:13 2012 New Revision: 1343163 URL: http://svn.apache.org/viewvc?rev=1343163&view=rev Log: MATH-792: - various methods to visit the entries of a RealVector (entries are unmodified), - default implementation in RealVector abstract class, - unit tests in abstract RealVectorAbstractClass, - all XxxRealVectorTest classes now extend RealVectorAbstractClass.
Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java (with props) Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVector.java commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVectorPreservingVisitor.java commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/ArrayRealVectorTest.java commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorTest.java commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/SparseRealVectorTest.java Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVector.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVector.java?rev=1343163&r1=1343162&r2=1343163&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVector.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVector.java Mon May 28 08:31:13 2012 @@ -22,6 +22,7 @@ import java.util.NoSuchElementException; import org.apache.commons.math3.exception.MathUnsupportedOperationException; import org.apache.commons.math3.exception.DimensionMismatchException; +import org.apache.commons.math3.exception.NumberIsTooSmallException; import org.apache.commons.math3.exception.OutOfRangeException; import org.apache.commons.math3.exception.MathArithmeticException; import org.apache.commons.math3.analysis.FunctionUtils; @@ -191,6 +192,37 @@ public abstract class RealVector { } /** + * Checks that the indices of a subvector are valid. + * + * @param start the index of the first entry of the subvector + * @param end the index of the last entry of the subvector (inclusive) + * @throws OutOfRangeException if {@code start} of {@code end} are not valid + * @throws NumberIsTooSmallException if {@code end < start} + */ + protected void checkIndices(final int start, final int end) { + final int dim = getDimension(); + if ((start < 0) || (start >= dim)) { + throw new OutOfRangeException(LocalizedFormats.INDEX, + Integer.valueOf(start), + Integer.valueOf(0), + Integer.valueOf(dim - 1)); + } + if ((end < 0) || (end >= dim)) { + throw new OutOfRangeException(LocalizedFormats.INDEX, + Integer.valueOf(end), + Integer.valueOf(0), + Integer.valueOf(dim - 1)); + } + if (end < start){ + // TODO Use more specific error message + throw new NumberIsTooSmallException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW, + Integer.valueOf(end), + Integer.valueOf(start), + false); + } + } + + /** * Compute the sum of this vector and {@code v}. * Returns a new vector. Does not change instance data. * @@ -807,9 +839,82 @@ public abstract class RealVector { return this; } + /** - * An entry in the vector. + * Visits (but does not change) all entries of this vector in default order + * (increasing index). + * + * @param visitor the visitor to be used to process the entries of this + * vector + * @return the value returned by {@link RealVectorPreservingVisitor#end()} + * at the end of the walk */ + public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor) { + final int dim = getDimension(); + visitor.start(dim, 0, dim - 1); + for (int i = 0; i < dim; i++) { + visitor.visit(i, getEntry(i)); + } + return visitor.end(); + } + + /** + * Visits (and possibly change) some entries of this vector in default order + * (increasing index). + * + * @param visitor visitor to be used to process the entries of this vector + * @param start the index of the first entry to be visited + * @param end the index of the last entry to be visited (inclusive) + * @return the value returned by {@link RealVectorPreservingVisitor#end()} + * at the end of the walk + * @throws org.apache.commons.math3.exception.OutOfRangeException if + * the indices are not valid. + */ + public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor, + int start, int end) { + checkIndices(start, end); + visitor.start(getDimension(), start, end); + for (int i = start; i <= end; i++) { + visitor.visit(i, getEntry(i)); + } + return visitor.end(); + } + + /** + * Visits (but does not change) all entries of this vector in optimized + * order. The order in which the entries are visited is selected so as to + * lead to the most efficient implementation; it might depend on the + * concrete implementation of this abstract class. + * + * @param visitor the visitor to be used to process the entries of this + * vector + * @return the value returned by {@link RealVectorPreservingVisitor#end()} + * at the end of the walk + */ + public double walkInOptimizedOrder(final RealVectorPreservingVisitor visitor) { + return walkInDefaultOrder(visitor); + } + + /** + * Visits (and possibly change) some entries of this vector in default order + * (increasing index). The order in which the entries are visited is + * selected so as to lead to the most efficient implementation; it might + * depend on the concrete implementation of this abstract class. + * + * @param visitor visitor to be used to process the entries of this vector + * @param start the index of the first entry to be visited + * @param end the index of the last entry to be visited (inclusive) + * @return the value returned by {@link RealVectorPreservingVisitor#end()} + * at the end of the walk + * @throws org.apache.commons.math3.exception.OutOfRangeException if + * the indices are not valid. + */ + public double walkInOptimizedOrder(final RealVectorPreservingVisitor visitor, + int start, int end) { + return walkInDefaultOrder(visitor, start, end); + } + + /** An entry in the vector. */ protected class Entry { /** Index of this entry. */ private int index; Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVectorPreservingVisitor.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVectorPreservingVisitor.java?rev=1343163&r1=1343162&r2=1343163&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVectorPreservingVisitor.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/RealVectorPreservingVisitor.java Mon May 28 08:31:13 2012 @@ -47,9 +47,12 @@ public interface RealVectorPreservingVis * End visiting a vector. This method is called once, after all entries of * the vector have been visited. * - * @return the value that the {@code walkInXxxOrder} must return + * @return the value returned by + * {@link RealVector#walkInDefaultOrder(RealVectorPreservingVisitor)}, + * {@link RealVector#walkInDefaultOrder(RealVectorPreservingVisitor, int, int)}, + * {@link RealVector#walkInOptimizedOrder(RealVectorPreservingVisitor)} + * or + * {@link RealVector#walkInOptimizedOrder(RealVectorPreservingVisitor, int, int) */ - // TODO Check above javadoc comment (add proper link to methods in - // RealVector class) double end(); } Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/ArrayRealVectorTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/ArrayRealVectorTest.java?rev=1343163&r1=1343162&r2=1343163&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/ArrayRealVectorTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/ArrayRealVectorTest.java Mon May 28 08:31:13 2012 @@ -59,7 +59,7 @@ import org.junit.Test; * * @version $Id$ */ -public class ArrayRealVectorTest { +public class ArrayRealVectorTest extends RealVectorAbstractTest { // protected double[][] ma1 = {{1d, 2d, 3d}, {4d, 5d, 6d}, {7d, 8d, 9d}}; @@ -1430,4 +1430,9 @@ public class ArrayRealVectorTest { Assert.assertEquals(msg + " " + i + " elements differ", m[i],n[i],tolerance); } } + + @Override + public RealVector create(final double[] data) { + return new ArrayRealVector(data, true); + } } Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java?rev=1343163&view=auto ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java (added) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java Mon May 28 08:31:13 2012 @@ -0,0 +1,231 @@ +package org.apache.commons.math3.linear; + +import java.util.Arrays; + +import junit.framework.Assert; + +import org.apache.commons.math3.exception.NumberIsTooSmallException; +import org.apache.commons.math3.exception.OutOfRangeException; +import org.junit.Test; + + +public abstract class RealVectorAbstractTest { + + public abstract RealVector create(double[] data); + + /** The whole vector is visited. */ + @Test + public void testWalkInDefaultOrderPreservingVisitor1() { + final double[] data = new double[] { + 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d + }; + final RealVector v = create(data); + final RealVectorPreservingVisitor visitor; + visitor = new RealVectorPreservingVisitor() { + + private int expectedIndex; + + public void visit(final int actualIndex, final double actualValue) { + Assert.assertEquals(expectedIndex, actualIndex); + Assert.assertEquals(Integer.toString(actualIndex), + data[actualIndex], actualValue, 0d); + ++expectedIndex; + } + + public void start(final int actualSize, final int actualStart, + final int actualEnd) { + Assert.assertEquals(data.length, actualSize); + Assert.assertEquals(0, actualStart); + Assert.assertEquals(data.length - 1, actualEnd); + expectedIndex = 0; + } + + public double end() { + return 0; + } + }; + v.walkInDefaultOrder(visitor); + } + + /** Visiting an invalid subvector. */ + @Test + public void testWalkInDefaultOrderPreservingVisitor2() { + final RealVector v = create(new double[5]); + try { + v.walkInDefaultOrder(null, -1, 4); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInDefaultOrder(null, 5, 4); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInDefaultOrder(null, 0, -1); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInDefaultOrder(null, 0, 5); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInDefaultOrder(null, 4, 0); + Assert.fail(); + } catch (NumberIsTooSmallException e) { + // Expected behavior + } + } + + /** Visiting a valid subvector. */ + @Test + public void testWalkInDefaultOrderPreservingVisitor3() { + final double[] data = new double[] { + 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d + }; + final int expectedStart = 2; + final int expectedEnd = 7; + final RealVector v = create(data); + final RealVectorPreservingVisitor visitor; + visitor = new RealVectorPreservingVisitor() { + + private int expectedIndex; + + public void visit(final int actualIndex, final double actualValue) { + Assert.assertEquals(expectedIndex, actualIndex); + Assert.assertEquals(Integer.toString(actualIndex), + data[actualIndex], actualValue, 0d); + ++expectedIndex; + } + + public void start(final int actualSize, final int actualStart, + final int actualEnd) { + Assert.assertEquals(data.length, actualSize); + Assert.assertEquals(expectedStart, actualStart); + Assert.assertEquals(expectedEnd, actualEnd); + expectedIndex = expectedStart; + } + + public double end() { + return 0; + } + }; + v.walkInDefaultOrder(visitor, expectedStart, expectedEnd); + } + + /** The whole vector is visited. */ + @Test + public void testWalkInOptimizedOrderPreservingVisitor1() { + final double[] data = new double[] { + 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d + }; + final RealVector v = create(data); + final RealVectorPreservingVisitor visitor; + visitor = new RealVectorPreservingVisitor() { + private final boolean[] visited = new boolean[data.length]; + + public void visit(final int actualIndex, final double actualValue) { + visited[actualIndex] = true; + Assert.assertEquals(Integer.toString(actualIndex), + data[actualIndex], actualValue, 0d); + } + + public void start(final int actualSize, final int actualStart, + final int actualEnd) { + Assert.assertEquals(data.length, actualSize); + Assert.assertEquals(0, actualStart); + Assert.assertEquals(data.length - 1, actualEnd); + Arrays.fill(visited, false); + } + + public double end() { + for (int i = 0; i < data.length; i++) { + Assert.assertTrue("entry " + i + "has not been visited", + visited[i]); + } + return 0; + } + }; + v.walkInOptimizedOrder(visitor); + } + + /** Visiting an invalid subvector. */ + @Test + public void testWalkInOptimizedOrderPreservingVisitor2() { + final RealVector v = create(new double[5]); + try { + v.walkInOptimizedOrder(null, -1, 4); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInOptimizedOrder(null, 5, 4); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInOptimizedOrder(null, 0, -1); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInOptimizedOrder(null, 0, 5); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInOptimizedOrder(null, 4, 0); + Assert.fail(); + } catch (NumberIsTooSmallException e) { + // Expected behavior + } + } + + /** Visiting a valid subvector. */ + @Test + public void testWalkInOptimizedOrderPreservingVisitor3() { + final double[] data = new double[] { + 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d + }; + final int expectedStart = 2; + final int expectedEnd = 7; + final RealVector v = create(data); + final RealVectorPreservingVisitor visitor; + visitor = new RealVectorPreservingVisitor() { + private final boolean[] visited = new boolean[data.length]; + + public void visit(final int actualIndex, final double actualValue) { + Assert.assertEquals(Integer.toString(actualIndex), + data[actualIndex], actualValue, 0d); + visited[actualIndex] = true; + } + + public void start(final int actualSize, final int actualStart, + final int actualEnd) { + Assert.assertEquals(data.length, actualSize); + Assert.assertEquals(expectedStart, actualStart); + Assert.assertEquals(expectedEnd, actualEnd); + Arrays.fill(visited, true); + } + + public double end() { + for (int i = expectedStart; i <= expectedEnd; i++) { + Assert.assertTrue("entry " + i + "has not been visited", + visited[i]); + } + return 0; + } + }; + v.walkInDefaultOrder(visitor, expectedStart, expectedEnd); + } +} Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorTest.java?rev=1343163&r1=1343162&r2=1343163&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/RealVectorTest.java Mon May 28 08:31:13 2012 @@ -28,7 +28,7 @@ import java.util.Random; /** * Tests for {@link RealVector}. */ -public class RealVectorTest { +public class RealVectorTest extends RealVectorAbstractTest{ private double[] vec1 = { 1d, 2d, 3d, 4d, 5d }; private double[] vec2 = { -3d, 0d, 0d, 2d, 1d }; @@ -330,4 +330,9 @@ public class RealVectorTest { Assert.assertEquals(v[i] + inc, x.getEntry(i), 0); } } + + @Override + public RealVector create(final double[] data) { + return new OpenMapRealVector(data); + } } Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/SparseRealVectorTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/SparseRealVectorTest.java?rev=1343163&r1=1343162&r2=1343163&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/SparseRealVectorTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/SparseRealVectorTest.java Mon May 28 08:31:13 2012 @@ -57,7 +57,7 @@ import org.apache.commons.math3.analysis * * @version $Id$ */ -public class SparseRealVectorTest { +public class SparseRealVectorTest extends RealVectorAbstractTest { // protected double[][] ma1 = {{1d, 2d, 3d}, {4d, 5d, 6d}, {7d, 8d, 9d}}; @@ -955,4 +955,9 @@ public class SparseRealVectorTest { u.ebeMultiply(v1); u.ebeDivide(v1); } + + @Override + public RealVector create(double[] data) { + return new OpenMapRealVector(data); + } }