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