001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.rng.sampling.distribution; 018 019import org.apache.commons.rng.UniformRandomProvider; 020 021/** 022 * Sampling from a Gaussian distribution with given mean and 023 * standard deviation. 024 * 025 * <h2>Note</h2> 026 * 027 * <p>The mean and standard deviation are validated to ensure they are finite. This prevents 028 * generation of NaN samples by avoiding invalid arithmetic (inf * 0 or inf - inf). 029 * However use of an extremely large standard deviation and/or mean may result in samples that are 030 * infinite; that is the parameters are not validated to prevent truncation of the output 031 * distribution. 032 * 033 * @since 1.1 034 */ 035public class GaussianSampler implements SharedStateContinuousSampler { 036 /** Mean. */ 037 private final double mean; 038 /** standardDeviation. */ 039 private final double standardDeviation; 040 /** Normalized Gaussian sampler. */ 041 private final NormalizedGaussianSampler normalized; 042 043 /** 044 * @param normalized Generator of N(0,1) Gaussian distributed random numbers. 045 * @param mean Mean of the Gaussian distribution. 046 * @param standardDeviation Standard deviation of the Gaussian distribution. 047 * @throws IllegalArgumentException if {@code standardDeviation <= 0} or is infinite; 048 * or {@code mean} is infinite 049 */ 050 public GaussianSampler(NormalizedGaussianSampler normalized, 051 double mean, 052 double standardDeviation) { 053 if (!(standardDeviation > 0 && standardDeviation < Double.POSITIVE_INFINITY)) { 054 throw new IllegalArgumentException( 055 "standard deviation is not strictly positive and finite: " + standardDeviation); 056 } 057 if (!Double.isFinite(mean)) { 058 throw new IllegalArgumentException("mean is not finite: " + mean); 059 } 060 this.normalized = normalized; 061 this.mean = mean; 062 this.standardDeviation = standardDeviation; 063 } 064 065 /** 066 * @param rng Generator of uniformly distributed random numbers. 067 * @param source Source to copy. 068 */ 069 private GaussianSampler(UniformRandomProvider rng, 070 GaussianSampler source) { 071 this.mean = source.mean; 072 this.standardDeviation = source.standardDeviation; 073 this.normalized = InternalUtils.newNormalizedGaussianSampler(source.normalized, rng); 074 } 075 076 /** {@inheritDoc} */ 077 @Override 078 public double sample() { 079 return standardDeviation * normalized.sample() + mean; 080 } 081 082 /** {@inheritDoc} */ 083 @Override 084 public String toString() { 085 return "Gaussian deviate [" + normalized.toString() + "]"; 086 } 087 088 /** 089 * {@inheritDoc} 090 * 091 * <p>Note: This function is available if the underlying {@link NormalizedGaussianSampler} 092 * is a {@link org.apache.commons.rng.sampling.SharedStateSampler SharedStateSampler}. 093 * Otherwise a run-time exception is thrown.</p> 094 * 095 * @throws UnsupportedOperationException if the underlying sampler is not a 096 * {@link org.apache.commons.rng.sampling.SharedStateSampler SharedStateSampler} or 097 * does not return a {@link NormalizedGaussianSampler} when sharing state. 098 * 099 * @since 1.3 100 */ 101 @Override 102 public SharedStateContinuousSampler withUniformRandomProvider(UniformRandomProvider rng) { 103 return new GaussianSampler(rng, this); 104 } 105 106 /** 107 * Create a new normalised Gaussian sampler. 108 * 109 * <p>Note: The shared-state functionality is available if the {@link NormalizedGaussianSampler} 110 * is a {@link org.apache.commons.rng.sampling.SharedStateSampler SharedStateSampler}. 111 * Otherwise a run-time exception will be thrown when the sampler is used to share state.</p> 112 * 113 * @param normalized Generator of N(0,1) Gaussian distributed random numbers. 114 * @param mean Mean of the Gaussian distribution. 115 * @param standardDeviation Standard deviation of the Gaussian distribution. 116 * @return the sampler 117 * @throws IllegalArgumentException if {@code standardDeviation <= 0} or is infinite; 118 * or {@code mean} is infinite 119 * @see #withUniformRandomProvider(UniformRandomProvider) 120 * @since 1.3 121 */ 122 public static SharedStateContinuousSampler of(NormalizedGaussianSampler normalized, 123 double mean, 124 double standardDeviation) { 125 return new GaussianSampler(normalized, mean, standardDeviation); 126 } 127}