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 }