From d0d9683df8398696147e7ee1fcffb2e4e957008c Mon Sep 17 00:00:00 2001 From: Daniel Mueller Date: Sat, 4 Apr 2020 14:39:19 -0700 Subject: Remove vendored dependencies While it appears that by now we actually can get successful builds without Cargo insisting on Internet access by virtue of using the --frozen flag, maintaining vendored dependencies is somewhat of a pain point. This state will also get worse with upcoming changes that replace argparse in favor of structopt and pull in a slew of new dependencies by doing so. Then there is also the repository structure aspect, which is non-standard due to the way we vendor dependencies and a potential source of confusion. In order to fix these problems, this change removes all the vendored dependencies we have. Delete subrepo argparse/:argparse Delete subrepo base32/:base32 Delete subrepo cc/:cc Delete subrepo cfg-if/:cfg-if Delete subrepo getrandom/:getrandom Delete subrepo lazy-static/:lazy-static Delete subrepo libc/:libc Delete subrepo nitrokey-sys/:nitrokey-sys Delete subrepo nitrokey/:nitrokey Delete subrepo rand/:rand --- rand/rand_distr/src/poisson.rs | 233 ----------------------------------------- 1 file changed, 233 deletions(-) delete mode 100644 rand/rand_distr/src/poisson.rs (limited to 'rand/rand_distr/src/poisson.rs') diff --git a/rand/rand_distr/src/poisson.rs b/rand/rand_distr/src/poisson.rs deleted file mode 100644 index 4f4a0b7..0000000 --- a/rand/rand_distr/src/poisson.rs +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2018 Developers of the Rand project. -// Copyright 2016-2017 The Rust Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The Poisson distribution. - -use rand::Rng; -use crate::{Distribution, Cauchy, Standard}; -use crate::utils::Float; - -/// The Poisson distribution `Poisson(lambda)`. -/// -/// This distribution has a density function: -/// `f(k) = lambda^k * exp(-lambda) / k!` for `k >= 0`. -/// -/// # Example -/// -/// ``` -/// use rand_distr::{Poisson, Distribution}; -/// -/// let poi = Poisson::new(2.0).unwrap(); -/// let v: u64 = poi.sample(&mut rand::thread_rng()); -/// println!("{} is from a Poisson(2) distribution", v); -/// ``` -#[derive(Clone, Copy, Debug)] -pub struct Poisson { - lambda: N, - // precalculated values - exp_lambda: N, - log_lambda: N, - sqrt_2lambda: N, - magic_val: N, -} - -/// Error type returned from `Poisson::new`. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum Error { - /// `lambda <= 0` or `nan`. - ShapeTooSmall, -} - -impl Poisson -where Standard: Distribution -{ - /// Construct a new `Poisson` with the given shape parameter - /// `lambda`. - pub fn new(lambda: N) -> Result, Error> { - if !(lambda > N::from(0.0)) { - return Err(Error::ShapeTooSmall); - } - let log_lambda = lambda.ln(); - Ok(Poisson { - lambda, - exp_lambda: (-lambda).exp(), - log_lambda, - sqrt_2lambda: (N::from(2.0) * lambda).sqrt(), - magic_val: lambda * log_lambda - (N::from(1.0) + lambda).log_gamma(), - }) - } -} - -impl Distribution for Poisson -where Standard: Distribution -{ - #[inline] - fn sample(&self, rng: &mut R) -> N { - // using the algorithm from Numerical Recipes in C - - // for low expected values use the Knuth method - if self.lambda < N::from(12.0) { - let mut result = N::from(0.); - let mut p = N::from(1.0); - while p > self.exp_lambda { - p *= rng.gen::(); - result += N::from(1.); - } - result - N::from(1.) - } - // high expected values - rejection method - else { - // we use the Cauchy distribution as the comparison distribution - // f(x) ~ 1/(1+x^2) - let cauchy = Cauchy::new(N::from(0.0), N::from(1.0)).unwrap(); - let mut result; - - loop { - let mut comp_dev; - - loop { - // draw from the Cauchy distribution - comp_dev = rng.sample(cauchy); - // shift the peak of the comparison ditribution - result = self.sqrt_2lambda * comp_dev + self.lambda; - // repeat the drawing until we are in the range of possible values - if result >= N::from(0.0) { - break; - } - } - // now the result is a random variable greater than 0 with Cauchy distribution - // the result should be an integer value - result = result.floor(); - - // this is the ratio of the Poisson distribution to the comparison distribution - // the magic value scales the distribution function to a range of approximately 0-1 - // since it is not exact, we multiply the ratio by 0.9 to avoid ratios greater than 1 - // this doesn't change the resulting distribution, only increases the rate of failed drawings - let check = N::from(0.9) * (N::from(1.0) + comp_dev * comp_dev) - * (result * self.log_lambda - (N::from(1.0) + result).log_gamma() - self.magic_val).exp(); - - // check with uniform random value - if below the threshold, we are within the target distribution - if rng.gen::() <= check { - break; - } - } - result - } - } -} - -impl Distribution for Poisson -where Standard: Distribution -{ - #[inline] - fn sample(&self, rng: &mut R) -> u64 { - let result: N = self.sample(rng); - result.to_u64().unwrap() - } -} - -#[cfg(test)] -mod test { - use crate::Distribution; - use super::Poisson; - - #[test] - fn test_poisson_10() { - let poisson = Poisson::new(10.0).unwrap(); - let mut rng = crate::test::rng(123); - let mut sum_u64 = 0; - let mut sum_f64 = 0.; - for _ in 0..1000 { - let s_u64: u64 = poisson.sample(&mut rng); - let s_f64: f64 = poisson.sample(&mut rng); - sum_u64 += s_u64; - sum_f64 += s_f64; - } - let avg_u64 = (sum_u64 as f64) / 1000.0; - let avg_f64 = sum_f64 / 1000.0; - println!("Poisson averages: {} (u64) {} (f64)", avg_u64, avg_f64); - for &avg in &[avg_u64, avg_f64] { - assert!((avg - 10.0).abs() < 0.5); // not 100% certain, but probable enough - } - } - - #[test] - fn test_poisson_15() { - // Take the 'high expected values' path - let poisson = Poisson::new(15.0).unwrap(); - let mut rng = crate::test::rng(123); - let mut sum_u64 = 0; - let mut sum_f64 = 0.; - for _ in 0..1000 { - let s_u64: u64 = poisson.sample(&mut rng); - let s_f64: f64 = poisson.sample(&mut rng); - sum_u64 += s_u64; - sum_f64 += s_f64; - } - let avg_u64 = (sum_u64 as f64) / 1000.0; - let avg_f64 = sum_f64 / 1000.0; - println!("Poisson average: {} (u64) {} (f64)", avg_u64, avg_f64); - for &avg in &[avg_u64, avg_f64] { - assert!((avg - 15.0).abs() < 0.5); // not 100% certain, but probable enough - } - } - - #[test] - fn test_poisson_10_f32() { - let poisson = Poisson::new(10.0f32).unwrap(); - let mut rng = crate::test::rng(123); - let mut sum_u64 = 0; - let mut sum_f32 = 0.; - for _ in 0..1000 { - let s_u64: u64 = poisson.sample(&mut rng); - let s_f32: f32 = poisson.sample(&mut rng); - sum_u64 += s_u64; - sum_f32 += s_f32; - } - let avg_u64 = (sum_u64 as f32) / 1000.0; - let avg_f32 = sum_f32 / 1000.0; - println!("Poisson averages: {} (u64) {} (f32)", avg_u64, avg_f32); - for &avg in &[avg_u64, avg_f32] { - assert!((avg - 10.0).abs() < 0.5); // not 100% certain, but probable enough - } - } - - #[test] - fn test_poisson_15_f32() { - // Take the 'high expected values' path - let poisson = Poisson::new(15.0f32).unwrap(); - let mut rng = crate::test::rng(123); - let mut sum_u64 = 0; - let mut sum_f32 = 0.; - for _ in 0..1000 { - let s_u64: u64 = poisson.sample(&mut rng); - let s_f32: f32 = poisson.sample(&mut rng); - sum_u64 += s_u64; - sum_f32 += s_f32; - } - let avg_u64 = (sum_u64 as f32) / 1000.0; - let avg_f32 = sum_f32 / 1000.0; - println!("Poisson average: {} (u64) {} (f32)", avg_u64, avg_f32); - for &avg in &[avg_u64, avg_f32] { - assert!((avg - 15.0).abs() < 0.5); // not 100% certain, but probable enough - } - } - - #[test] - #[should_panic] - fn test_poisson_invalid_lambda_zero() { - Poisson::new(0.0).unwrap(); - } - - #[test] - #[should_panic] - fn test_poisson_invalid_lambda_neg() { - Poisson::new(-10.0).unwrap(); - } -} -- cgit v1.2.1