Merge pull request #575 from vks/triangular
Implement triangular distribution
This commit is contained in:
@@ -98,6 +98,8 @@
|
||||
//! - [`ChiSquared`] distribution
|
||||
//! - [`StudentT`] distribution
|
||||
//! - [`FisherF`] distribution
|
||||
//! - Triangular distribution:
|
||||
//! - [`Triangular`] distribution
|
||||
//! - Multivariate probability distributions
|
||||
//! - [`Dirichlet`] distribution
|
||||
//! - [`UnitSphereSurface`] distribution
|
||||
@@ -168,6 +170,7 @@
|
||||
//! [`Standard`]: struct.Standard.html
|
||||
//! [`StandardNormal`]: struct.StandardNormal.html
|
||||
//! [`StudentT`]: struct.StudentT.html
|
||||
//! [`Triangular`]: struct.Triangular.html
|
||||
//! [`Uniform`]: struct.Uniform.html
|
||||
//! [`Uniform::new`]: struct.Uniform.html#method.new
|
||||
//! [`Uniform::new_inclusive`]: struct.Uniform.html#method.new_inclusive
|
||||
@@ -192,6 +195,7 @@ pub use self::bernoulli::Bernoulli;
|
||||
#[cfg(feature="std")] pub use self::binomial::Binomial;
|
||||
#[cfg(feature="std")] pub use self::cauchy::Cauchy;
|
||||
#[cfg(feature="std")] pub use self::dirichlet::Dirichlet;
|
||||
#[cfg(feature="std")] pub use self::triangular::Triangular;
|
||||
|
||||
pub mod uniform;
|
||||
mod bernoulli;
|
||||
@@ -206,6 +210,7 @@ mod bernoulli;
|
||||
#[cfg(feature="std")] mod binomial;
|
||||
#[cfg(feature="std")] mod cauchy;
|
||||
#[cfg(feature="std")] mod dirichlet;
|
||||
#[cfg(feature="std")] mod triangular;
|
||||
|
||||
mod float;
|
||||
mod integer;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//! The triangular distribution.
|
||||
|
||||
use Rng;
|
||||
use distributions::{Distribution, Standard};
|
||||
|
||||
/// The triangular distribution.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{Triangular, Distribution};
|
||||
///
|
||||
/// let d = Triangular::new(0., 5., 2.5);
|
||||
/// let v = d.sample(&mut rand::thread_rng());
|
||||
/// println!("{} is from a triangular distribution", v);
|
||||
/// ```
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Triangular {
|
||||
min: f64,
|
||||
max: f64,
|
||||
mode: f64,
|
||||
}
|
||||
|
||||
impl Triangular {
|
||||
/// Construct a new `Triangular` with minimum `min`, maximum `max` and mode
|
||||
/// `mode`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If `max < mode`, `mode < max` or `max == min`.
|
||||
///
|
||||
#[inline]
|
||||
pub fn new(min: f64, max: f64, mode: f64) -> Triangular {
|
||||
assert!(max >= mode);
|
||||
assert!(mode >= min);
|
||||
assert!(max != min);
|
||||
Triangular { min, max, mode }
|
||||
}
|
||||
}
|
||||
|
||||
impl Distribution<f64> for Triangular {
|
||||
#[inline]
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
|
||||
let f: f64 = rng.sample(Standard);
|
||||
let diff_mode_min = self.mode - self.min;
|
||||
let diff_max_min = self.max - self.min;
|
||||
if f * diff_max_min < diff_mode_min {
|
||||
self.min + (f * diff_max_min * diff_mode_min).sqrt()
|
||||
} else {
|
||||
self.max - ((1. - f) * diff_max_min * (self.max - self.mode)).sqrt()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use distributions::Distribution;
|
||||
use super::Triangular;
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
for &(min, max, mode) in &[
|
||||
(-1., 1., 0.), (1., 2., 1.), (5., 25., 25.), (1e-5, 1e5, 1e-3),
|
||||
(0., 1., 0.9), (-4., -0.5, -2.), (-13.039, 8.41, 1.17),
|
||||
] {
|
||||
println!("{} {} {}", min, max, mode);
|
||||
let _ = Triangular::new(min, max, mode);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let norm = Triangular::new(0., 1., 0.5);
|
||||
let mut rng = ::test::rng(1);
|
||||
for _ in 0..1000 {
|
||||
norm.sample(&mut rng);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user