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.sampling.distribution;
18  
19  import org.apache.commons.rng.UniformRandomProvider;
20  import org.apache.commons.rng.core.source32.IntProvider;
21  import org.apache.commons.rng.sampling.RandomAssert;
22  import org.apache.commons.rng.simple.RandomSource;
23  import org.junit.Assert;
24  import org.junit.Test;
25  
26  /**
27   * Test for the {@link MarsagliaNormalizedGaussianSampler}.
28   */
29  public class MarsagliaNormalisedGaussianSamplerTest {
30      /**
31       * Test the SharedStateSampler implementation.
32       */
33      @Test
34      public void testSharedStateSampler() {
35          final UniformRandomProvider rng1 = RandomSource.create(RandomSource.SPLIT_MIX_64, 0L);
36          final UniformRandomProvider rng2 = RandomSource.create(RandomSource.SPLIT_MIX_64, 0L);
37          final SharedStateContinuousSampler sampler1 =
38              MarsagliaNormalizedGaussianSampler.<MarsagliaNormalizedGaussianSampler>of(rng1);
39          final SharedStateContinuousSampler sampler2 = sampler1.withUniformRandomProvider(rng2);
40          RandomAssert.assertProduceSameSequence(sampler1, sampler2);
41      }
42  
43      /**
44       * Test the edge case where the pair of samples are rejected. This occurs when the distance
45       * of the pair is outside the unit circle or lies on the origin.
46       */
47      @Test
48      public void testSamplePairIsRejected() {
49          final double value = 0.25;
50          final UniformRandomProvider rng = new IntProvider() {
51              private int i;
52  
53              @Override
54              public int next() {
55                  // Not used
56                  return 0;
57              }
58  
59              @Override
60              public double nextDouble() {
61                  i++;
62                  if (i <= 2) {
63                      // First two samples are one.
64                      // This is outside the unit circle.
65                      return 1.0;
66                  }
67                  if (i <= 4) {
68                      // Next two samples are 0.5.
69                      // The pair lies at the origin.
70                      return 0.5;
71                  }
72                  return value;
73              }
74          };
75  
76          final MarsagliaNormalizedGaussianSampler sampler = new MarsagliaNormalizedGaussianSampler(rng);
77  
78          // Compute as per the algorithm
79          final double x = 2 * value - 1;
80          final double r2 = x * x + x * x;
81          final double expected = x * Math.sqrt(-2 * Math.log(r2) / r2);
82          Assert.assertEquals(expected, sampler.sample(), 0);
83      }
84  }