View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.rng.simple;
18  
19  import java.util.Random;
20  
21  import org.apache.commons.rng.UniformRandomProvider;
22  import org.apache.commons.rng.core.source64.LongProvider;
23  import org.junit.Assert;
24  import org.junit.Test;
25  
26  /**
27   * Tests for the {@link JDKRandomWrapper} class.
28   */
29  public class JDKRandomWrapperTest {
30      /**
31       * Test all the methods shared by Random and UniformRandomProvider are equivalent.
32       */
33      @Test
34      public void testJDKRandomEquivalence() {
35          // Initialize.
36          final long seed = RandomSource.createLong();
37          final Random rng1 = new Random(seed);
38          final UniformRandomProvider rng2 = new JDKRandomWrapper(new Random(seed));
39          checkSameSequence(rng1, rng2);
40      }
41  
42      /**
43       * Ensure that both generators produce the same sequences.
44       *
45       * @param rng1 RNG.
46       * @param rng2 RNG.
47       */
48      private static void checkSameSequence(Random rng1,
49                                            UniformRandomProvider rng2) {
50          for (int i = 0; i < 4; i++) {
51              Assert.assertEquals(rng1.nextInt(),
52                                  rng2.nextInt());
53          }
54          for (int i = 0; i < 7; i++) {
55              Assert.assertEquals(rng1.nextLong(),
56                                  rng2.nextLong());
57          }
58          for (int i = 0; i < 9; i++) {
59              Assert.assertEquals(rng1.nextFloat(),
60                                  rng2.nextFloat(),
61                                  0f);
62          }
63          for (int i = 0; i < 12; i++) {
64              Assert.assertEquals(rng1.nextDouble(),
65                                  rng2.nextDouble(),
66                                  0d);
67          }
68          for (int i = 0; i < 18; i++) {
69              Assert.assertEquals(rng1.nextBoolean(),
70                                  rng2.nextBoolean());
71          }
72          for (int i = 0; i < 19; i++) {
73              final int max = i + 123456;
74              Assert.assertEquals(rng1.nextInt(max),
75                                  rng2.nextInt(max));
76          }
77  
78          final int len = 233;
79          final byte[] store1 = new byte[len];
80          final byte[] store2 = new byte[len];
81          rng1.nextBytes(store1);
82          rng2.nextBytes(store2);
83          for (int i = 0; i < len; i++) {
84              Assert.assertEquals(store1[i],
85                                  store2[i]);
86          }
87      }
88  
89      /**
90       * Test {@link UniformRandomProvider#nextLong(long)} matches that from the core
91       * BaseProvider implementation.
92       */
93      @Test
94      public void testNextLongInRange() {
95          final long seed = RandomSource.createLong();
96          // This will use the RNG core BaseProvider implementation.
97          // Use a LongProvider to directly use the Random::nextLong method
98          // which is different from IntProvider::nextLong.
99          final UniformRandomProvider rng1 = new LongProvider() {
100             private final Random random = new Random(seed);
101 
102             @Override
103             public long next() {
104                 return random.nextLong();
105             }
106         };
107         final UniformRandomProvider rng2 = new JDKRandomWrapper(new Random(seed));
108 
109         // Test cases
110         // 1              : Smallest range
111         // 256            : Integer power of 2
112         // 56757          : Integer range
113         // 1L << 32       : Non-integer power of 2
114         // (1L << 62) + 1 : Worst case for rejection rate for the algorithm.
115         //                  Reject probability is approximately 0.5 thus the test hits
116         //                  all code paths.
117         for (final long max : new long[] {1, 256, 56757, 1L << 32, (1L << 62) + 1}) {
118             for (int i = 0; i < 10; i++) {
119                 Assert.assertEquals(rng1.nextLong(max),
120                                     rng2.nextLong(max));
121             }
122         }
123     }
124 
125     @Test(expected = IllegalArgumentException.class)
126     public void testNextLongInRangeThrows() {
127         final UniformRandomProvider rng1 = new JDKRandomWrapper(new Random(5675767L));
128         rng1.nextLong(0);
129     }
130 
131     /**
132      * Test the bytes created by {@link UniformRandomProvider#nextBytes(byte[], int, int)} matches
133      * {@link Random#nextBytes(byte[])}.
134      */
135     @Test
136     public void testNextByteInRange() {
137         final long seed = RandomSource.createLong();
138         final Random rng1 = new Random(seed);
139         final UniformRandomProvider rng2 = new JDKRandomWrapper(new Random(seed));
140 
141         checkSameBytes(rng1, rng2, 1, 0, 1);
142         checkSameBytes(rng1, rng2, 100, 0, 100);
143         checkSameBytes(rng1, rng2, 100, 10, 90);
144         checkSameBytes(rng1, rng2, 245, 67, 34);
145     }
146 
147     /**
148      * Ensure that the bytes produced in a sub-range of a byte array by
149      * {@link UniformRandomProvider#nextBytes(byte[], int, int)} match the bytes created
150      * by the JDK {@link Random#nextBytes(byte[])}.
151      *
152      * @param rng1 JDK Random.
153      * @param rng2 RNG.
154      * @param size Size of byte array.
155      * @param start Index at which to start inserting the generated bytes.
156      * @param len Number of bytes to insert.
157      */
158     private static void checkSameBytes(Random rng1,
159                                        UniformRandomProvider rng2,
160                                        int size, int start, int length) {
161         final byte[] store1 = new byte[length];
162         final byte[] store2 = new byte[size];
163         rng1.nextBytes(store1);
164         rng2.nextBytes(store2, start, length);
165         for (int i = 0; i < length; i++) {
166             Assert.assertEquals(store1[i],
167                                 store2[i + start]);
168         }
169     }
170 }