1 // Copyright 2018 Developers of the Rand project. 2 // 3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license 5 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your 6 // option. This file may not be copied, modified, or distributed 7 // except according to those terms. 8 //! The triangular distribution. 9 10 use Rng; 11 use distributions::{Distribution, Standard}; 12 13 /// The triangular distribution. 14 /// 15 /// # Example 16 /// 17 /// ```rust 18 /// use rand::distributions::{Triangular, Distribution}; 19 /// 20 /// let d = Triangular::new(0., 5., 2.5); 21 /// let v = d.sample(&mut rand::thread_rng()); 22 /// println!("{} is from a triangular distribution", v); 23 /// ``` 24 #[derive(Clone, Copy, Debug)] 25 pub struct Triangular { 26 min: f64, 27 max: f64, 28 mode: f64, 29 } 30 31 impl Triangular { 32 /// Construct a new `Triangular` with minimum `min`, maximum `max` and mode 33 /// `mode`. 34 /// 35 /// # Panics 36 /// 37 /// If `max < mode`, `mode < max` or `max == min`. 38 /// 39 #[inline] new(min: f64, max: f64, mode: f64) -> Triangular40 pub fn new(min: f64, max: f64, mode: f64) -> Triangular { 41 assert!(max >= mode); 42 assert!(mode >= min); 43 assert!(max != min); 44 Triangular { min, max, mode } 45 } 46 } 47 48 impl Distribution<f64> for Triangular { 49 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f6450 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 { 51 let f: f64 = rng.sample(Standard); 52 let diff_mode_min = self.mode - self.min; 53 let diff_max_min = self.max - self.min; 54 if f * diff_max_min < diff_mode_min { 55 self.min + (f * diff_max_min * diff_mode_min).sqrt() 56 } else { 57 self.max - ((1. - f) * diff_max_min * (self.max - self.mode)).sqrt() 58 } 59 } 60 } 61 62 #[cfg(test)] 63 mod test { 64 use distributions::Distribution; 65 use super::Triangular; 66 67 #[test] test_new()68 fn test_new() { 69 for &(min, max, mode) in &[ 70 (-1., 1., 0.), (1., 2., 1.), (5., 25., 25.), (1e-5, 1e5, 1e-3), 71 (0., 1., 0.9), (-4., -0.5, -2.), (-13.039, 8.41, 1.17), 72 ] { 73 println!("{} {} {}", min, max, mode); 74 let _ = Triangular::new(min, max, mode); 75 } 76 } 77 78 #[test] test_sample()79 fn test_sample() { 80 let norm = Triangular::new(0., 1., 0.5); 81 let mut rng = ::test::rng(1); 82 for _ in 0..1000 { 83 norm.sample(&mut rng); 84 } 85 } 86 } 87