diff --git a/checkstyle.xml b/checkstyle.xml index 73989f4f0..4a17529a2 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -1,196 +1,118 @@ - + + - - - - + This configuration file was written by the eclipse-cs plugin configuration editor +--> + + - - - - + - - - - - - - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - + + - - - + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - + - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - diff --git a/src/main/java/org/apache/commons/math3/linear/ArrayRealVector.java b/src/main/java/org/apache/commons/math3/linear/ArrayRealVector.java index ff9492c0d..5426d2fe3 100644 --- a/src/main/java/org/apache/commons/math3/linear/ArrayRealVector.java +++ b/src/main/java/org/apache/commons/math3/linear/ArrayRealVector.java @@ -881,4 +881,26 @@ public class ArrayRealVector extends RealVector implements Serializable { } return this; } + + /** {@inheritDoc} */ + @Override + public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor) { + visitor.start(data.length, 0, data.length - 1); + for (int i = 0; i < data.length; i++) { + visitor.visit(i, data[i]); + } + return visitor.end(); + } + + /** {@inheritDoc} */ + @Override + public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor, + final int start, final int end) { + checkIndices(start, end); + visitor.start(data.length, start, end); + for (int i = start; i <= end; i++) { + visitor.visit(i, data[i]); + } + return visitor.end(); + } } diff --git a/src/main/java/org/apache/commons/math3/linear/RealVector.java b/src/main/java/org/apache/commons/math3/linear/RealVector.java index 39f96d24a..8ed27fb35 100644 --- a/src/main/java/org/apache/commons/math3/linear/RealVector.java +++ b/src/main/java/org/apache/commons/math3/linear/RealVector.java @@ -835,7 +835,7 @@ public abstract class RealVector { /** - * Visits (but does not change) all entries of this vector in default order + * Visits (but does not alter) all entries of this vector in default order * (increasing index). * * @param visitor the visitor to be used to process the entries of this @@ -853,7 +853,7 @@ public abstract class RealVector { } /** - * Visits (and possibly change) some entries of this vector in default order + * Visits (but does not alter) some entries of this vector in default order * (increasing index). * * @param visitor visitor to be used to process the entries of this vector @@ -865,7 +865,7 @@ public abstract class RealVector { * the indices are not valid. */ public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor, - int start, int end) { + int start, int end) { checkIndices(start, end); visitor.start(getDimension(), start, end); for (int i = start; i <= end; i++) { @@ -875,7 +875,7 @@ public abstract class RealVector { } /** - * Visits (but does not change) all entries of this vector in optimized + * Visits (but does not alter) 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. @@ -890,10 +890,10 @@ public abstract class RealVector { } /** - * 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. + * Visits (but does not alter) some 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 visitor to be used to process the entries of this vector * @param start the index of the first entry to be visited @@ -908,6 +908,80 @@ public abstract class RealVector { return walkInDefaultOrder(visitor, start, end); } + /** + * Visits (and possibly alters) all entries of this vector in default order + * (increasing index). + * + * @param visitor the visitor to be used to process and modify the entries + * of this vector + * @return the value returned by {@link RealVectorChangingVisitor#end()} + * at the end of the walk + */ + public double walkInDefaultOrder(final RealVectorChangingVisitor visitor) { + final int dim = getDimension(); + visitor.start(dim, 0, dim - 1); + for (int i = 0; i < dim; i++) { + setEntry(i, visitor.visit(i, getEntry(i))); + } + return visitor.end(); + } + + /** + * Visits (and possibly alters) 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 RealVectorChangingVisitor#end()} + * at the end of the walk + * @throws org.apache.commons.math3.exception.OutOfRangeException if + * the indices are not valid. + */ + public double walkInDefaultOrder(final RealVectorChangingVisitor visitor, + int start, int end) { + checkIndices(start, end); + visitor.start(getDimension(), start, end); + for (int i = start; i <= end; i++) { + setEntry(i, visitor.visit(i, getEntry(i))); + } + return visitor.end(); + } + + /** + * Visits (and possibly alters) 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 RealVectorChangingVisitor#end()} + * at the end of the walk + */ + public double walkInOptimizedOrder(final RealVectorChangingVisitor visitor) { + return walkInDefaultOrder(visitor); + } + + /** + * Visits (and possibly change) some 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 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 RealVectorChangingVisitor#end()} + * at the end of the walk + * @throws org.apache.commons.math3.exception.OutOfRangeException if + * the indices are not valid. + */ + public double walkInOptimizedOrder(final RealVectorChangingVisitor visitor, + int start, int end) { + return walkInDefaultOrder(visitor, start, end); + } + /** An entry in the vector. */ protected class Entry { /** Index of this entry. */ diff --git a/src/main/java/org/apache/commons/math3/linear/RealVectorChangingVisitor.java b/src/main/java/org/apache/commons/math3/linear/RealVectorChangingVisitor.java new file mode 100644 index 000000000..91c40a48a --- /dev/null +++ b/src/main/java/org/apache/commons/math3/linear/RealVectorChangingVisitor.java @@ -0,0 +1,59 @@ +/* + * 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.math3.linear; + +/** + * This interface defines a visitor for the entries of a vector. Visitors + * implementing this interface may alter the entries of the vector being + * visited. + * + * @version $Id$ + * @since 3.1 + */ +public interface RealVectorChangingVisitor { + /** + * Start visiting a vector. This method is called once, before any entry + * of the vector is visited. + * + * @param dimension the size of the vector + * @param start the index of the first entry to be visited + * @param end the index of the last entry to be visited (inclusive) + */ + void start(int dimension, int start, int end); + + /** + * Visit one entry of the vector. + * + * @param index the index of the entry being visited + * @param value the value of the entry being visited + * @return the new value of the entry being visited + */ + double visit(int index, double value); + + /** + * End visiting a vector. This method is called once, after all entries of + * the vector have been visited. + * + * @return the value returned by + * {@link RealVector#walkInDefaultOrder(RealVectorChangingVisitor)}, + * {@link RealVector#walkInDefaultOrder(RealVectorChangingVisitor, int, int)}, + * {@link RealVector#walkInOptimizedOrder(RealVectorChangingVisitor)} + * or + * {@link RealVector#walkInOptimizedOrder(RealVectorChangingVisitor, int, int)} + */ + double end(); +} diff --git a/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java b/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java index d41953c42..5e82f966b 100644 --- a/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java +++ b/src/test/java/org/apache/commons/math3/linear/RealVectorAbstractTest.java @@ -41,7 +41,7 @@ public abstract class RealVectorAbstractTest { } public double end() { - return 0; + return 0.0; } }; v.walkInDefaultOrder(visitor); @@ -51,32 +51,47 @@ public abstract class RealVectorAbstractTest { @Test public void testWalkInDefaultOrderPreservingVisitor2() { final RealVector v = create(new double[5]); + final RealVectorPreservingVisitor visitor; + visitor = new RealVectorPreservingVisitor() { + + public void visit(int index, double value) { + // Do nothing + } + + public void start(int dimension, int start, int end) { + // Do nothing + } + + public double end() { + return 0.0; + } + }; try { - v.walkInDefaultOrder(null, -1, 4); + v.walkInDefaultOrder(visitor, -1, 4); Assert.fail(); } catch (OutOfRangeException e) { // Expected behavior } try { - v.walkInDefaultOrder(null, 5, 4); + v.walkInDefaultOrder(visitor, 5, 4); Assert.fail(); } catch (OutOfRangeException e) { // Expected behavior } try { - v.walkInDefaultOrder(null, 0, -1); + v.walkInDefaultOrder(visitor, 0, -1); Assert.fail(); } catch (OutOfRangeException e) { // Expected behavior } try { - v.walkInDefaultOrder(null, 0, 5); + v.walkInDefaultOrder(visitor, 0, 5); Assert.fail(); } catch (OutOfRangeException e) { // Expected behavior } try { - v.walkInDefaultOrder(null, 4, 0); + v.walkInDefaultOrder(visitor, 4, 0); Assert.fail(); } catch (NumberIsTooSmallException e) { // Expected behavior @@ -113,7 +128,7 @@ public abstract class RealVectorAbstractTest { } public double end() { - return 0; + return 0.0; } }; v.walkInDefaultOrder(visitor, expectedStart, expectedEnd); @@ -149,7 +164,7 @@ public abstract class RealVectorAbstractTest { Assert.assertTrue("entry " + i + "has not been visited", visited[i]); } - return 0; + return 0.0; } }; v.walkInOptimizedOrder(visitor); @@ -159,32 +174,47 @@ public abstract class RealVectorAbstractTest { @Test public void testWalkInOptimizedOrderPreservingVisitor2() { final RealVector v = create(new double[5]); + final RealVectorPreservingVisitor visitor; + visitor = new RealVectorPreservingVisitor() { + + public void visit(int index, double value) { + // Do nothing + } + + public void start(int dimension, int start, int end) { + // Do nothing + } + + public double end() { + return 0.0; + } + }; try { - v.walkInOptimizedOrder(null, -1, 4); + v.walkInOptimizedOrder(visitor, -1, 4); Assert.fail(); } catch (OutOfRangeException e) { // Expected behavior } try { - v.walkInOptimizedOrder(null, 5, 4); + v.walkInOptimizedOrder(visitor, 5, 4); Assert.fail(); } catch (OutOfRangeException e) { // Expected behavior } try { - v.walkInOptimizedOrder(null, 0, -1); + v.walkInOptimizedOrder(visitor, 0, -1); Assert.fail(); } catch (OutOfRangeException e) { // Expected behavior } try { - v.walkInOptimizedOrder(null, 0, 5); + v.walkInOptimizedOrder(visitor, 0, 5); Assert.fail(); } catch (OutOfRangeException e) { // Expected behavior } try { - v.walkInOptimizedOrder(null, 4, 0); + v.walkInOptimizedOrder(visitor, 4, 0); Assert.fail(); } catch (NumberIsTooSmallException e) { // Expected behavior @@ -223,9 +253,271 @@ public abstract class RealVectorAbstractTest { Assert.assertTrue("entry " + i + "has not been visited", visited[i]); } - return 0; + return 0.0; } }; v.walkInOptimizedOrder(visitor, expectedStart, expectedEnd); } + + /** The whole vector is visited. */ + @Test + public void testWalkInDefaultOrderChangingVisitor1() { + final double[] data = new double[] { + 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d + }; + final RealVector v = create(data); + final RealVectorChangingVisitor visitor; + visitor = new RealVectorChangingVisitor() { + + private int expectedIndex; + + public double visit(final int actualIndex, final double actualValue) { + Assert.assertEquals(expectedIndex, actualIndex); + Assert.assertEquals(Integer.toString(actualIndex), + data[actualIndex], actualValue, 0d); + ++expectedIndex; + return actualIndex + actualValue; + } + + 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.0; + } + }; + v.walkInDefaultOrder(visitor); + for (int i = 0; i < data.length; i++) { + Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0); + } + } + + /** Visiting an invalid subvector. */ + @Test + public void testWalkInDefaultOrderChangingVisitor2() { + final RealVector v = create(new double[5]); + final RealVectorChangingVisitor visitor; + visitor = new RealVectorChangingVisitor() { + + public double visit(int index, double value) { + return 0.0; + } + + public void start(int dimension, int start, int end) { + // Do nothing + } + + public double end() { + return 0.0; + } + }; + try { + v.walkInDefaultOrder(visitor, -1, 4); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInDefaultOrder(visitor, 5, 4); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInDefaultOrder(visitor, 0, -1); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInDefaultOrder(visitor, 0, 5); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInDefaultOrder(visitor, 4, 0); + Assert.fail(); + } catch (NumberIsTooSmallException e) { + // Expected behavior + } + } + + /** Visiting a valid subvector. */ + @Test + public void testWalkInDefaultOrderChangingVisitor3() { + 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 RealVectorChangingVisitor visitor; + visitor = new RealVectorChangingVisitor() { + + private int expectedIndex; + + public double visit(final int actualIndex, final double actualValue) { + Assert.assertEquals(expectedIndex, actualIndex); + Assert.assertEquals(Integer.toString(actualIndex), + data[actualIndex], actualValue, 0d); + ++expectedIndex; + return actualIndex + actualValue; + } + + 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.0; + } + }; + v.walkInDefaultOrder(visitor, expectedStart, expectedEnd); + for (int i = expectedStart; i <= expectedEnd; i++) { + Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0); + } + } + + /** The whole vector is visited. */ + @Test + public void testWalkInOptimizedOrderChangingVisitor1() { + final double[] data = new double[] { + 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d + }; + final RealVector v = create(data); + final RealVectorChangingVisitor visitor; + visitor = new RealVectorChangingVisitor() { + private final boolean[] visited = new boolean[data.length]; + + public double visit(final int actualIndex, final double actualValue) { + visited[actualIndex] = true; + Assert.assertEquals(Integer.toString(actualIndex), + data[actualIndex], actualValue, 0d); + return actualIndex + actualValue; + } + + 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.0; + } + }; + v.walkInOptimizedOrder(visitor); + for (int i = 0; i < data.length; i++) { + Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0); + } + } + + /** Visiting an invalid subvector. */ + @Test + public void testWalkInOptimizedOrderChangingVisitor2() { + final RealVector v = create(new double[5]); + final RealVectorChangingVisitor visitor; + visitor = new RealVectorChangingVisitor() { + + public double visit(int index, double value) { + return 0.0; + } + + public void start(int dimension, int start, int end) { + // Do nothing + } + + public double end() { + return 0.0; + } + }; + try { + v.walkInOptimizedOrder(visitor, -1, 4); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInOptimizedOrder(visitor, 5, 4); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInOptimizedOrder(visitor, 0, -1); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInOptimizedOrder(visitor, 0, 5); + Assert.fail(); + } catch (OutOfRangeException e) { + // Expected behavior + } + try { + v.walkInOptimizedOrder(visitor, 4, 0); + Assert.fail(); + } catch (NumberIsTooSmallException e) { + // Expected behavior + } + } + + /** Visiting a valid subvector. */ + @Test + public void testWalkInOptimizedOrderChangingVisitor3() { + 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 RealVectorChangingVisitor visitor; + visitor = new RealVectorChangingVisitor() { + private final boolean[] visited = new boolean[data.length]; + + public double visit(final int actualIndex, final double actualValue) { + Assert.assertEquals(Integer.toString(actualIndex), + data[actualIndex], actualValue, 0d); + visited[actualIndex] = true; + return actualIndex + actualValue; + } + + 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.0; + } + }; + v.walkInOptimizedOrder(visitor, expectedStart, expectedEnd); + for (int i = expectedStart; i <= expectedEnd; i++) { + Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0); + } + } }