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