88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- //! The normal distribution .
11+ //! The normal and derived distributions .
1212
1313use rand:: { Rng , Rand , Open01 } ;
1414use rand:: distributions:: { ziggurat, ziggurat_tables, Sample , IndependentSample } ;
@@ -108,6 +108,46 @@ impl IndependentSample<f64> for Normal {
108108 }
109109}
110110
111+
112+ /// The log-normal distribution `ln N(mean, std_dev**2)`.
113+ ///
114+ /// If `X` is log-normal distributed, then `ln(X)` is `N(mean,
115+ /// std_dev**2)` distributed.
116+ ///
117+ /// # Example
118+ ///
119+ /// ```rust
120+ /// use std::rand;
121+ /// use std::rand::distributions::{LogNormal, IndependentSample};
122+ ///
123+ /// fn main() {
124+ /// // mean 2, standard deviation 3
125+ /// let log_normal = LogNormal::new(2.0, 3.0);
126+ /// let v = normal.ind_sample(&mut rand::task_rng());
127+ /// println!("{} is from an ln N(2, 9) distribution", v)
128+ /// }
129+ /// ```
130+ pub struct LogNormal {
131+ priv norm : Normal
132+ }
133+
134+ impl LogNormal {
135+ /// Construct a new `LogNormal` distribution with the given mean
136+ /// and standard deviation. Fails if `std_dev < 0`.
137+ pub fn new ( mean : f64 , std_dev : f64 ) -> LogNormal {
138+ assert ! ( std_dev >= 0.0 , "LogNormal::new called with `std_dev` < 0" ) ;
139+ LogNormal { norm : Normal :: new ( mean, std_dev) }
140+ }
141+ }
142+ impl Sample < f64 > for LogNormal {
143+ fn sample < R : Rng > ( & mut self , rng : & mut R ) -> f64 { self . ind_sample ( rng) }
144+ }
145+ impl IndependentSample < f64 > for LogNormal {
146+ fn ind_sample < R : Rng > ( & self , rng : & mut R ) -> f64 {
147+ self . norm . ind_sample ( rng) . exp ( )
148+ }
149+ }
150+
111151#[ cfg( test) ]
112152mod tests {
113153 use rand:: * ;
@@ -129,6 +169,22 @@ mod tests {
129169 fn test_normal_invalid_sd ( ) {
130170 Normal :: new ( 10.0 , -1.0 ) ;
131171 }
172+
173+
174+ #[ test]
175+ fn test_log_normal ( ) {
176+ let mut lnorm = LogNormal :: new ( 10.0 , 10.0 ) ;
177+ let mut rng = task_rng ( ) ;
178+ for _ in range ( 0 , 1000 ) {
179+ lnorm. sample ( & mut rng) ;
180+ lnorm. ind_sample ( & mut rng) ;
181+ }
182+ }
183+ #[ test]
184+ #[ should_fail]
185+ fn test_log_normal_invalid_sd ( ) {
186+ LogNormal :: new ( 10.0 , -1.0 ) ;
187+ }
132188}
133189
134190#[ cfg( test) ]
0 commit comments