Skip to content

Commit c31ff9c

Browse files
committed
Added IntRange class, one more method to PRNG.Smart and a suite of all tests
1 parent bd62e50 commit c31ff9c

File tree

4 files changed

+131
-34
lines changed

4 files changed

+131
-34
lines changed

src/main/java/org/thejavaguy/prng/generators/PRNG.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.thejavaguy.prng.generators;
22

3+
import org.thejavaguy.prng.generators.util.IntRange;
4+
35
public interface PRNG {
46
/**
57
* Returns pseudo-random integer in range [Integer.MIN_VALUE, Integer.MAX_VALUE]
@@ -47,16 +49,21 @@ public int nextInt(int lowerLimit, int upperLimit) {
4749
}
4850
//if branch handles negative integer overflow case, else branch handles normal case
4951
if (lowerLimit < 0 && upperLimit >= 0 && (upperLimit - lowerLimit) < 0) {
52+
IntRange range = new IntRange(lowerLimit, upperLimit);
5053
for (;;) {
5154
int ret = origin.nextInt();
52-
if (ret >= lowerLimit && ret <= upperLimit) {
55+
if (range.contains(ret)) {
5356
return ret;
5457
}
5558
}
5659
} else {
5760
return lowerLimit + nextInt(upperLimit - lowerLimit);
5861
}
5962
}
63+
64+
public int nextInt(IntRange range) {
65+
return nextInt(range.lowerLimit(), range.upperLimit());
66+
}
6067

6168
/**
6269
* Returns pseudo-random boolean
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.thejavaguy.prng.generators.util;
2+
3+
/**
4+
* @author Ivan Milosavljevic (TheJavaGuy)
5+
*/
6+
public final class IntRange {
7+
private final int lowerLimit;
8+
private final int upperLimit;
9+
10+
public IntRange(int lowerLimit, int upperLimit) {
11+
super();
12+
if (lowerLimit >= upperLimit) {
13+
throw new IllegalArgumentException(String.format(
14+
"upperLimit must be greater than lowerLimit, yet values are: lowerLimit = %d, upperLimit = %d",
15+
lowerLimit, upperLimit));
16+
}
17+
this.lowerLimit = lowerLimit;
18+
this.upperLimit = upperLimit;
19+
}
20+
21+
public int lowerLimit() {
22+
return lowerLimit;
23+
}
24+
25+
public int upperLimit() {
26+
return upperLimit;
27+
}
28+
29+
public long size() {
30+
return (long) upperLimit - lowerLimit + 1;
31+
}
32+
33+
public boolean contains(int candidate) {
34+
return lowerLimit <= candidate && candidate <= upperLimit;
35+
}
36+
37+
public boolean overlaps(IntRange other) {
38+
return this.contains(other.lowerLimit) || this.contains(other.upperLimit);
39+
}
40+
41+
@Override
42+
public String toString() {
43+
StringBuilder builder = new StringBuilder();
44+
builder.append("IntRange [lowerLimit=");
45+
builder.append(lowerLimit);
46+
builder.append(", upperLimit=");
47+
builder.append(upperLimit);
48+
builder.append("]");
49+
return builder.toString();
50+
}
51+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.thejavaguy.prng.generators;
2+
3+
import org.junit.runner.RunWith;
4+
import org.junit.runners.Suite;
5+
import org.junit.runners.Suite.SuiteClasses;
6+
7+
@RunWith(Suite.class)
8+
@SuiteClasses({ CMWCTest.class, MersenneTwisterTest.class, R250_521Test.class, R250Test.class, XorshiftPlusTest.class })
9+
public class AllTests {
10+
11+
}

src/test/java/org/thejavaguy/prng/generators/CommonTests.java

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
import static org.junit.Assert.*;
44

5+
import java.util.HashSet;
56
import java.util.Set;
67
import java.util.TreeSet;
78

89
import org.junit.After;
910
import org.junit.Before;
1011
import org.junit.Test;
12+
import org.thejavaguy.prng.generators.util.IntRange;
1113

1214
public abstract class CommonTests {
1315
private PRNG.Smart sut;
@@ -37,119 +39,145 @@ public void nextDouble_IsAlwaysGEQ0andL1() {
3739
@Test
3840
public void nextInt_WithUpperLimit_IsAlwaysWithinLimit() {
3941
int reps = 10_000_000;
42+
IntRange range = new IntRange(0, 10);
4043
Set<Integer> results = new TreeSet<>();
4144
for (int i = 0; i < reps; ++i) {
4245
int actual = sut.nextInt(10);
4346
results.add(actual);
44-
assertTrue(actual >= 0);
45-
assertTrue(actual <= 10);
47+
assertTrue(range.contains(actual));
4648
}
47-
assertEquals(11, results.size());
49+
assertEquals(range.size(), results.size());
4850
}
4951

5052
@Test
5153
public void nextInt_WithUpperLimit_IsAlwaysWithinLimit2() {
5254
int reps = 10_000_000;
55+
IntRange range = new IntRange(0, 1);
5356
for (int i = 0; i < reps; ++i) {
5457
int actual = sut.nextInt(1);
55-
assertTrue(actual >= 0);
56-
assertTrue(actual <= 1);
58+
assertTrue(range.contains(actual));
5759
}
5860
}
5961

6062
@Test
6163
public void nextInt_WithNegativeLimits_IsAlwaysWithinLimits() {
6264
int reps = 10_000_000;
65+
IntRange range = new IntRange(-10, -1);
6366
Set<Integer> results = new TreeSet<>();
6467
for (int i = 0; i < reps; ++i) {
65-
int actual = sut.nextInt(-10, -1);
68+
int actual = sut.nextInt(range);
6669
results.add(Integer.valueOf(actual));
67-
assertTrue(actual >= -10);
68-
assertTrue(actual <= -1);
70+
assertTrue(range.contains(actual));
6971
}
70-
assertEquals(10, results.size());
72+
assertEquals(range.size(), results.size());
7173
}
7274

7375
@Test
7476
public void nextByte_IsAlwaysWithinLimits() {
7577
int reps = 10_000_000;
78+
IntRange range = new IntRange(Byte.MIN_VALUE, Byte.MAX_VALUE);
7679
Set<Integer> results = new TreeSet<>();
7780
for (int i = 0; i < reps; ++i) {
7881
byte actual = sut.nextByte();
7982
results.add(Integer.valueOf(actual));
80-
assertTrue(actual >= -128);
81-
assertTrue(actual <= 127);
83+
assertTrue(range.contains(actual));
84+
}
85+
assertEquals(range.size(), results.size());
86+
}
87+
88+
@Test
89+
public void nextShort_IsAlwaysWithinLimits() {
90+
int reps = 10_000_000;
91+
IntRange range = new IntRange(Short.MIN_VALUE, Short.MAX_VALUE);
92+
Set<Short> results = new HashSet<>();
93+
for (int i = 0; i < reps; ++i) {
94+
short actual = sut.nextShort();
95+
results.add(Short.valueOf(actual));
96+
assertTrue(range.contains(actual));
8297
}
83-
assertEquals(256, results.size());
98+
assertEquals(range.size(), results.size());
99+
}
100+
101+
@Test
102+
public void nextChar_IsAlwaysWithinLimits() {
103+
int reps = 10_000_000;
104+
IntRange range = new IntRange(Character.MIN_VALUE, Character.MAX_VALUE);
105+
Set<Character> results = new HashSet<>();
106+
for (int i = 0; i < reps; ++i) {
107+
char actual = sut.nextChar();
108+
results.add(Character.valueOf(actual));
109+
assertTrue(range.contains(actual));
110+
}
111+
assertEquals(range.size(), results.size());
84112
}
85113

86114
@Test
87115
public void nextInt_WithNegativeEdgeLimits_IsAlwaysWithinLimits() {
88116
int reps = 10_000_000;
117+
IntRange range = new IntRange(Integer.MIN_VALUE, 0);
89118
for (int i = 0; i < reps; ++i) {
90-
int actual = sut.nextInt(Integer.MIN_VALUE, 0);
91-
assertTrue(actual >= Integer.MIN_VALUE);
92-
assertTrue(actual <= 0);
119+
int actual = sut.nextInt(range);
120+
assertTrue(range.contains(actual));
93121
}
94122
}
95123

96124
@Test
97125
public void nextInt_WithPositiveEdgeLimits_IsAlwaysWithinLimits() {
98126
int reps = 10_000_000;
127+
IntRange range = new IntRange(0, Integer.MAX_VALUE);
99128
for (int i = 0; i < reps; ++i) {
100-
int actual = sut.nextInt(0, Integer.MAX_VALUE);
101-
assertTrue(actual >= 0);
102-
assertTrue(actual <= Integer.MAX_VALUE);
129+
int actual = sut.nextInt(range);
130+
assertTrue(range.contains(actual));
103131
}
104132
}
105133

106134
@Test
107135
public void nextInt_WithEdgeLimits_IsAlwaysWithinLimits() {
108136
int reps = 10_000_000;
137+
IntRange range = new IntRange(Integer.MIN_VALUE, Integer.MAX_VALUE);
109138
for (int i = 0; i < reps; ++i) {
110-
int actual = sut.nextInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
111-
assertTrue(actual >= Integer.MIN_VALUE);
112-
assertTrue(actual <= Integer.MAX_VALUE);
139+
int actual = sut.nextInt(range);
140+
assertTrue(range.contains(actual));
113141
}
114142
}
115143

116144
@Test
117145
public void nextInt_WithWorstNegativeEdgeLimits_IsAlwaysWithinLimits() {
118146
int reps = 10_000_000;
147+
IntRange range = new IntRange(Integer.MIN_VALUE, Integer.MIN_VALUE + 1);
119148
for (int i = 0; i < reps; ++i) {
120-
int actual = sut.nextInt(Integer.MIN_VALUE, Integer.MIN_VALUE + 1);
121-
assertTrue(actual >= Integer.MIN_VALUE);
122-
assertTrue(actual <= Integer.MIN_VALUE + 1);
149+
int actual = sut.nextInt(range);
150+
assertTrue(range.contains(actual));
123151
}
124152
}
125153

126154
@Test
127155
public void nextInt_WithWorstPositiveEdgeLimits_IsAlwaysWithinLimits() {
128156
int reps = 10_000_000;
157+
IntRange range = new IntRange(Integer.MAX_VALUE - 1, Integer.MAX_VALUE);
129158
for (int i = 0; i < reps; ++i) {
130-
int actual = sut.nextInt(Integer.MAX_VALUE - 1, Integer.MAX_VALUE);
131-
assertTrue(actual >= Integer.MAX_VALUE - 1);
132-
assertTrue(actual <= Integer.MAX_VALUE);
159+
int actual = sut.nextInt(range);
160+
assertTrue(range.contains(actual));
133161
}
134162
}
135163

136164
@Test
137165
public void nextInt_WithPossibleNegativeOverflow_IsAlwaysWithinLimits() {
138166
int reps = 10_000_000;
167+
IntRange range = new IntRange(Integer.MIN_VALUE, 1);
139168
for (int i = 0; i < reps; ++i) {
140-
int actual = sut.nextInt(Integer.MIN_VALUE, 1);
141-
assertTrue(actual >= Integer.MIN_VALUE);
142-
assertTrue(actual <= 1);
169+
int actual = sut.nextInt(range);
170+
assertTrue(range.contains(actual));
143171
}
144172
}
145173

146174
@Test
147175
public void nextInt_WithPossiblePositiveOverflow_IsAlwaysWithinLimits() {
148176
int reps = 10_000_000;
177+
IntRange range = new IntRange(-1, Integer.MAX_VALUE);
149178
for (int i = 0; i < reps; ++i) {
150-
int actual = sut.nextInt(-1, Integer.MAX_VALUE);
151-
assertTrue(actual >= -1);
152-
assertTrue(actual <= Integer.MAX_VALUE);
179+
int actual = sut.nextInt(range);
180+
assertTrue(range.contains(actual));
153181
}
154182
}
155183
}

0 commit comments

Comments
 (0)