@@ -152,6 +152,136 @@ public void testNextBinomialThreadLocal() {
152152 }
153153 }
154154
155+ @ Test
156+ public void testNextCauchyRandom () {
157+ final int TRIALS = 8000 ;
158+ Random r = new Random (42 );
159+ double [] scale = {1 , 2 , 4 };
160+ final double sqrt2 = Math .sqrt (2 );
161+ for (double s : scale ) {
162+ double [] boundaries = { -s *(sqrt2 +1 ), -s , -s *(sqrt2 -1 ), 0 , s *(sqrt2 -1 ), s , s *(sqrt2 +1 )};
163+ int [] buckets = new int [8 ];
164+ for (int j = 0 ; j < TRIALS ; j ++) {
165+ double v = RandomVariates .nextCauchy (s , r );
166+ int i = 0 ;
167+ for (; i < boundaries .length ; i ++) {
168+ if (v < boundaries [i ]) break ;
169+ }
170+ buckets [i ]++;
171+ }
172+ double chi = chiSquare (buckets );
173+ // critical value for 8-1=7 degrees of freedom is 14.07 (at the .95 level).
174+ assertTrue ("Verifying chi square statistic below .95 critical value: chi=" +chi +" crit=14.07" , chi <= 14.07 );
175+ }
176+ double median = 5.0 ;
177+ double s = 1.0 ;
178+ double [] boundaries = { median - s *(sqrt2 +1 ), median - s , median - s *(sqrt2 -1 ), median , median + s *(sqrt2 -1 ), median + s , median + s *(sqrt2 +1 )};
179+ int [] buckets = new int [8 ];
180+ for (int j = 0 ; j < TRIALS ; j ++) {
181+ double v = RandomVariates .nextCauchy (median , s , r );
182+ int i = 0 ;
183+ for (; i < boundaries .length ; i ++) {
184+ if (v < boundaries [i ]) break ;
185+ }
186+ buckets [i ]++;
187+ }
188+ double chi = chiSquare (buckets );
189+ // critical value for 8-1=7 degrees of freedom is 14.07 (at the .95 level).
190+ assertTrue ("Verifying chi square statistic below .95 critical value: chi=" +chi +" crit=14.07" , chi <= 14.07 );
191+ }
192+
193+ @ Test
194+ public void testNextCauchyThreadLocalRandom () {
195+ // Since we cannot seed ThreadLocalRandom, this test case is
196+ // not 100% replicable. Additionally, we know that this version of
197+ // the method simply calls the version that takes a Random as a parameter.
198+ // Since we did test that version for goodness of fit,
199+ // and since replication is not possible without a seed, we simply verify
200+ // that over a large number of trials that samples are generated in each of the buckets
201+ // used for the goodness of fit tests in the class Random case.
202+ final int TRIALS = 800 ;
203+ double [] scale = {1 , 2 , 4 };
204+ final double sqrt2 = Math .sqrt (2 );
205+ for (double s : scale ) {
206+ double [] boundaries = { -s *(sqrt2 +1 ), -s , -s *(sqrt2 -1 ), 0 , s *(sqrt2 -1 ), s , s *(sqrt2 +1 )};
207+ int [] buckets = new int [8 ];
208+ for (int j = 0 ; j < TRIALS ; j ++) {
209+ double v = RandomVariates .nextCauchy (s );
210+ int i = 0 ;
211+ for (; i < boundaries .length ; i ++) {
212+ if (v < boundaries [i ]) break ;
213+ }
214+ buckets [i ]++;
215+ }
216+ for (int i = 0 ; i < buckets .length ; i ++) {
217+ assertTrue ("verifying at least 1 sample in each bucket, scale=" +s + " bucket=" +i , buckets [i ] > 0 );
218+ }
219+ }
220+ double median = 5.0 ;
221+ double s = 1.0 ;
222+ double [] boundaries = { median - s *(sqrt2 +1 ), median - s , median - s *(sqrt2 -1 ), median , median + s *(sqrt2 -1 ), median + s , median + s *(sqrt2 +1 )};
223+ int [] buckets = new int [8 ];
224+ for (int j = 0 ; j < TRIALS ; j ++) {
225+ double v = RandomVariates .nextCauchy (median , s );
226+ int i = 0 ;
227+ for (; i < boundaries .length ; i ++) {
228+ if (v < boundaries [i ]) break ;
229+ }
230+ buckets [i ]++;
231+ }
232+ for (int i = 0 ; i < buckets .length ; i ++) {
233+ assertTrue ("verifying at least 1 sample in each bucket, median=5 bucket=" +i , buckets [i ] > 0 );
234+ }
235+ }
236+
237+ @ Test
238+ public void testNextCauchySplittableRandom () {
239+ final int TRIALS = 8000 ;
240+ SplittableRandom r = new SplittableRandom (53 );
241+ double [] scale = {1 , 2 , 4 };
242+ final double sqrt2 = Math .sqrt (2 );
243+ for (double s : scale ) {
244+ double [] boundaries = { -s *(sqrt2 +1 ), -s , -s *(sqrt2 -1 ), 0 , s *(sqrt2 -1 ), s , s *(sqrt2 +1 )};
245+ int [] buckets = new int [8 ];
246+ for (int j = 0 ; j < TRIALS ; j ++) {
247+ double v = RandomVariates .nextCauchy (s , r );
248+ int i = 0 ;
249+ for (; i < boundaries .length ; i ++) {
250+ if (v < boundaries [i ]) break ;
251+ }
252+ buckets [i ]++;
253+ }
254+ double chi = chiSquare (buckets );
255+ // critical value for 8-1=7 degrees of freedom is 14.07 (at the .95 level).
256+ assertTrue ("Verifying chi square statistic below .95 critical value: chi=" +chi +" crit=14.07" , chi <= 14.07 );
257+ }
258+ double median = 5.0 ;
259+ double s = 1.0 ;
260+ double [] boundaries = { median - s *(sqrt2 +1 ), median - s , median - s *(sqrt2 -1 ), median , median + s *(sqrt2 -1 ), median + s , median + s *(sqrt2 +1 )};
261+ int [] buckets = new int [8 ];
262+ for (int j = 0 ; j < TRIALS ; j ++) {
263+ double v = RandomVariates .nextCauchy (median , s , r );
264+ int i = 0 ;
265+ for (; i < boundaries .length ; i ++) {
266+ if (v < boundaries [i ]) break ;
267+ }
268+ buckets [i ]++;
269+ }
270+ double chi = chiSquare (buckets );
271+ // critical value for 8-1=7 degrees of freedom is 14.07 (at the .95 level).
272+ assertTrue ("Verifying chi square statistic below .95 critical value: chi=" +chi +" crit=14.07" , chi <= 14.07 );
273+ }
274+
275+ private double chiSquare (int [] buckets ) {
276+ int n = 0 ;
277+ int v = 0 ;
278+ for (int i = 0 ; i < buckets .length ; i ++) {
279+ n += buckets [i ];
280+ v += (buckets [i ]*buckets [i ]);
281+ }
282+ return v * buckets .length * 1.0 / n - n ;
283+ }
284+
155285 private double chiSquare (int [] buckets , double [] dist ) {
156286 double v = 0 ;
157287 int n = 0 ;
0 commit comments