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  
18  package org.apache.commons.rng.examples.sampling;
19  
20  import org.apache.commons.rng.UniformRandomProvider;
21  import org.apache.commons.rng.simple.RandomSource;
22  
23  import picocli.CommandLine.Command;
24  import picocli.CommandLine.Mixin;
25  import picocli.CommandLine.Option;
26  
27  import java.util.concurrent.Callable;
28  
29  import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler;
30  import org.apache.commons.rng.sampling.distribution.ZigguratSampler;
31  import org.apache.commons.rng.sampling.distribution.MarsagliaNormalizedGaussianSampler;
32  import org.apache.commons.rng.sampling.distribution.BoxMullerNormalizedGaussianSampler;
33  import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
34  
35  /**
36   * Creates 2D plot of sampling output.
37   * It is a "manual" check that could help ensure that no artifacts
38   * exist in some tiny region of the expected range, due to loss of
39   * accuracy, e.g. when porting C code based on 32-bits "float" to
40   * "Commons RNG" that uses Java "double" (64-bits).
41   */
42  @Command(name = "visual",
43           description = "Show output from a tiny region of the sampler.")
44  class UniformSamplingVisualCheckCommand implements Callable<Void> {
45      /** The standard options. */
46      @Mixin
47      private StandardOptions reusableOptions;
48  
49      /** The lower bound of the tiny range. */
50      @Option(names = {"-l", "--low"},
51              description = "The lower bound (default: ${DEFAULT-VALUE}).")
52      private float lo = 0.1f;
53  
54      /** The number of bands of the tiny range. */
55      @Option(names = {"-b", "--bands"},
56              description = "The number of bands for the range (default: ${DEFAULT-VALUE}).")
57      private int bands = 2;
58  
59      /** Number of samples to be generated. */
60      @Option(names = {"-s", "--samples"},
61          description = "The number of samples in the tiny range (default: ${DEFAULT-VALUE}).")
62      private int numSamples = 50;
63  
64      /** RNG. */
65      private final UniformRandomProvider rng = RandomSource.XOR_SHIFT_1024_S_PHI.create();
66      /** Samplers. */
67      private final ContinuousSampler[] samplers = {
68          ZigguratNormalizedGaussianSampler.of(rng),
69          MarsagliaNormalizedGaussianSampler.of(rng),
70          BoxMullerNormalizedGaussianSampler.of(rng),
71          ZigguratSampler.NormalizedGaussian.of(rng),
72      };
73  
74      // Allow System.out
75      // CHECKSTYLE: stop RegexpCheck
76  
77      /**
78       * Prints a template generators list to stdout.
79       */
80      @Override
81      public Void call() {
82          float hi = lo;
83          for (int i = 0; i < bands; i++) {
84              hi = Math.nextUp(hi);
85          }
86          System.out.printf("# lower=%.16e%n", lo);
87          System.out.printf("# upper=%.16e%n", hi);
88  
89          for (int i = 0; i < samplers.length; i++) {
90              System.out.printf("# [%d] %s%n", i, samplers[i].getClass().getSimpleName());
91          }
92  
93          for (int n = 0; n < numSamples; n++) {
94              System.out.printf("[%d]", n);
95  
96              for (final ContinuousSampler s : samplers) {
97                  double r = s.sample();
98                  while (r < lo || r > hi) {
99                      // Discard numbers outside the tiny region.
100                     r = s.sample();
101                 }
102                 System.out.printf("\t%.16e", r);
103             }
104 
105             System.out.println();
106         }
107 
108         return null;
109     }
110 }