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
21 /**
22 * <a href="https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform">
23 * Box-Muller algorithm</a> for sampling from a Gaussian distribution.
24 *
25 * <p>Sampling uses:</p>
26 *
27 * <ul>
28 * <li>{@link UniformRandomProvider#nextDouble()}
29 * <li>{@link UniformRandomProvider#nextLong()}
30 * </ul>
31 *
32 * @since 1.0
33 *
34 * @deprecated Since version 1.1. Please use {@link BoxMullerNormalizedGaussianSampler}
35 * and {@link GaussianSampler} instead.
36 */
37 @Deprecated
38 public class BoxMullerGaussianSampler
39 extends SamplerBase
40 implements ContinuousSampler {
41 /** Next gaussian. */
42 private double nextGaussian = Double.NaN;
43 /** Mean. */
44 private final double mean;
45 /** standardDeviation. */
46 private final double standardDeviation;
47 /** Underlying source of randomness. */
48 private final UniformRandomProvider rng;
49
50 /**
51 * Create an instance.
52 *
53 * @param rng Generator of uniformly distributed random numbers.
54 * @param mean Mean of the Gaussian distribution.
55 * @param standardDeviation Standard deviation of the Gaussian distribution.
56 * @throws IllegalArgumentException if {@code standardDeviation <= 0}
57 */
58 public BoxMullerGaussianSampler(UniformRandomProvider rng,
59 double mean,
60 double standardDeviation) {
61 this(mean, InternalUtils.requireStrictlyPositiveFinite(standardDeviation, "standardDeviation"), rng);
62 }
63
64 /**
65 * @param rng Generator of uniformly distributed random numbers.
66 * @param mean Mean of the Gaussian distribution.
67 * @param standardDeviation Standard deviation of the Gaussian distribution.
68 */
69 private BoxMullerGaussianSampler(double mean,
70 double standardDeviation,
71 UniformRandomProvider rng) {
72 super(null);
73 this.rng = rng;
74 this.mean = mean;
75 this.standardDeviation = standardDeviation;
76 }
77
78 /** {@inheritDoc} */
79 @Override
80 public double sample() {
81 final double random;
82 if (Double.isNaN(nextGaussian)) {
83 // Generate a pair of Gaussian numbers.
84
85 // Avoid zero for the uniform deviate y.
86 // The extreme tail of the sample is:
87 // y = 2^-53
88 // r = 8.57167
89 final double x = rng.nextDouble();
90 final double y = InternalUtils.makeNonZeroDouble(rng.nextLong());
91 final double alpha = 2 * Math.PI * x;
92 final double r = Math.sqrt(-2 * Math.log(y));
93
94 // Return the first element of the generated pair.
95 random = r * Math.cos(alpha);
96
97 // Keep second element of the pair for next invocation.
98 nextGaussian = r * Math.sin(alpha);
99 } else {
100 // Use the second element of the pair (generated at the
101 // previous invocation).
102 random = nextGaussian;
103
104 // Both elements of the pair have been used.
105 nextGaussian = Double.NaN;
106 }
107
108 return standardDeviation * random + mean;
109 }
110
111 /** {@inheritDoc} */
112 @Override
113 public String toString() {
114 return "Box-Muller Gaussian deviate [" + rng.toString() + "]";
115 }
116 }