From fa1aa44c7623fb2142e588c59eaf56db7bc237eb Mon Sep 17 00:00:00 2001 From: Gilles Date: Sat, 31 Oct 2015 15:36:35 +0100 Subject: [PATCH] MATH-1286 New "Range" inner class that holds a field with the number of elements of the range. An instance of this class replaces the anonymous class returned by the "range" method. --- src/changes/changes.xml | 3 + .../commons/math4/util/IntegerSequence.java | 74 +++++++++++++++---- .../math4/util/IntegerSequenceTest.java | 47 ++++++++++-- 3 files changed, 102 insertions(+), 22 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 55a8fcbbb..d31605cc7 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,6 +54,9 @@ If the output is not quite correct, check for invisible trailing spaces! + + New "Range" inner class of "o.a.c.m.util.IntegerSequence". + Updated reference in ZipfDistribution's javadoc. diff --git a/src/main/java/org/apache/commons/math4/util/IntegerSequence.java b/src/main/java/org/apache/commons/math4/util/IntegerSequence.java index 1a16b0c6d..233ce3a77 100644 --- a/src/main/java/org/apache/commons/math4/util/IntegerSequence.java +++ b/src/main/java/org/apache/commons/math4/util/IntegerSequence.java @@ -42,8 +42,8 @@ public class IntegerSequence { * @param end Last value of the range. * @return a range. */ - public static Iterable range(int start, - int end) { + public static Range range(int start, + int end) { return range(start, end, 1); } @@ -58,19 +58,63 @@ public class IntegerSequence { * @param step Increment. * @return a range. */ - public static Iterable range(final int start, - final int max, - final int step) { - return new Iterable() { - /** {@inheritDoc} */ - @Override - public Iterator iterator() { - return Incrementor.create() - .withStart(start) - .withMaximalCount(max + (step > 0 ? 1 : -1)) - .withIncrement(step); - } - }; + public static Range range(final int start, + final int max, + final int step) { + return new Range(start, max, step); + } + + /** + * Generates a sequence of integers. + */ + public static class Range implements Iterable { + /** Number of integers contained in this range. */ + private final int size; + /** First value. */ + private final int start; + /** Final value. */ + private final int max; + /** Increment. */ + private final int step; + + /** + * Creates a sequence \( a_i, i < 0 <= n \) + * where \( a_i = start + i * step \) + * and \( n \) is such that \( a_n <= max \) and \( a_{n+1} > max \). + * + * @param start First value of the range. + * @param max Last value of the range that satisfies the above + * construction rule. + * @param step Increment. + */ + public Range(int start, + int max, + int step) { + this.start = start; + this.max = max; + this.step = step; + + final int s = (max - start) / step + 1; + this.size = s < 0 ? 0 : s; + } + + /** + * Gets the number of elements contained in the range. + * + * @return the size of the range. + */ + public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override + public Iterator iterator() { + return Incrementor.create() + .withStart(start) + .withMaximalCount(max + (step > 0 ? 1 : -1)) + .withIncrement(step); + } } /** diff --git a/src/test/java/org/apache/commons/math4/util/IntegerSequenceTest.java b/src/test/java/org/apache/commons/math4/util/IntegerSequenceTest.java index d1a67646d..25eec4f15 100644 --- a/src/test/java/org/apache/commons/math4/util/IntegerSequenceTest.java +++ b/src/test/java/org/apache/commons/math4/util/IntegerSequenceTest.java @@ -26,6 +26,27 @@ import org.junit.Test; * Tests for {@link IntegerSequence} and {@link IntegerSequence#Incrementor}. */ public class IntegerSequenceTest { + @Test + public void testRangeMultipleIterations() { + // Check that we can iterate several times using the same instance. + final int start = 1; + final int max = 7; + final int step = 2; + + final List seq = new ArrayList(); + final IntegerSequence.Range r = IntegerSequence.range(start, max, step); + + final int numTimes = 3; + for (int n = 0; n < numTimes; n++) { + seq.clear(); + for (Integer i : r) { + seq.add(i); + } + Assert.assertEquals(4, seq.size()); + Assert.assertEquals(seq.size(), r.size()); + } + } + @Test public void testIncreasingRange() { final int start = 1; @@ -33,11 +54,13 @@ public class IntegerSequenceTest { final int step = 2; final List seq = new ArrayList(); - for (Integer i : IntegerSequence.range(start, max, step)) { + final IntegerSequence.Range r = IntegerSequence.range(start, max, step); + for (Integer i : r) { seq.add(i); } Assert.assertEquals(4, seq.size()); + Assert.assertEquals(seq.size(), r.size()); for (int i = 0; i < seq.size(); i++) { Assert.assertEquals(start + i * step, seq.get(i).intValue()); } @@ -50,11 +73,13 @@ public class IntegerSequenceTest { final int step = 2; final List seq = new ArrayList(); - for (Integer i : IntegerSequence.range(start, max, step)) { + final IntegerSequence.Range r = IntegerSequence.range(start, max, step); + for (Integer i : r) { seq.add(i); } Assert.assertEquals(5, seq.size()); + Assert.assertEquals(seq.size(), r.size()); for (int i = 0; i < seq.size(); i++) { Assert.assertEquals(start + i * step, seq.get(i).intValue()); } @@ -67,11 +92,13 @@ public class IntegerSequenceTest { final int step = -3; final List seq = new ArrayList(); - for (Integer i : IntegerSequence.range(start, max, step)) { + final IntegerSequence.Range r = IntegerSequence.range(start, max, step); + for (Integer i : r) { seq.add(i); } Assert.assertEquals(7, seq.size()); + Assert.assertEquals(seq.size(), r.size()); for (int i = 0; i < seq.size(); i++) { Assert.assertEquals(start + i * step, seq.get(i).intValue()); } @@ -84,11 +111,13 @@ public class IntegerSequenceTest { final int step = -1; final List seq = new ArrayList(); - for (Integer i : IntegerSequence.range(start, max, step)) { + final IntegerSequence.Range r = IntegerSequence.range(start, max, step); + for (Integer i : r) { seq.add(i); } Assert.assertEquals(1, seq.size()); + Assert.assertEquals(seq.size(), r.size()); Assert.assertEquals(start, seq.get(0).intValue()); } @@ -110,14 +139,16 @@ public class IntegerSequenceTest { @Test public void testEmptyRange() { final int start = 2; - final int end = 1; + final int end = 0; final List seq = new ArrayList(); - for (Integer i : IntegerSequence.range(start, end)) { + final IntegerSequence.Range r = IntegerSequence.range(start, end); + for (Integer i : r) { seq.add(i); } Assert.assertEquals(0, seq.size()); + Assert.assertEquals(seq.size(), r.size()); } @Test @@ -127,11 +158,13 @@ public class IntegerSequenceTest { final int step = -1; final List seq = new ArrayList(); - for (Integer i : IntegerSequence.range(start, max, step)) { + final IntegerSequence.Range r = IntegerSequence.range(start, max, step); + for (Integer i : r) { seq.add(i); } Assert.assertEquals(0, seq.size()); + Assert.assertEquals(seq.size(), r.size()); } @Test(expected=MaxCountExceededException.class)