]> git.proxmox.com Git - rustc.git/blob - vendor/rand-0.7.3/src/distributions/unit_circle.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / vendor / rand-0.7.3 / src / distributions / unit_circle.rs
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
9 #![allow(deprecated)]
10 #![allow(clippy::all)]
11
12 use crate::distributions::{Distribution, Uniform};
13 use crate::Rng;
14
15 /// Samples uniformly from the edge of the unit circle in two dimensions.
16 ///
17 /// Implemented via a method by von Neumann[^1].
18 ///
19 /// [^1]: von Neumann, J. (1951) [*Various Techniques Used in Connection with
20 /// Random Digits.*](https://mcnp.lanl.gov/pdf_files/nbs_vonneumann.pdf)
21 /// NBS Appl. Math. Ser., No. 12. Washington, DC: U.S. Government Printing
22 /// Office, pp. 36-38.
23 #[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
24 #[derive(Clone, Copy, Debug)]
25 pub struct UnitCircle;
26
27 impl UnitCircle {
28 /// Construct a new `UnitCircle` distribution.
29 #[inline]
30 pub fn new() -> UnitCircle {
31 UnitCircle
32 }
33 }
34
35 impl Distribution<[f64; 2]> for UnitCircle {
36 #[inline]
37 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> [f64; 2] {
38 let uniform = Uniform::new(-1., 1.);
39 let mut x1;
40 let mut x2;
41 let mut sum;
42 loop {
43 x1 = uniform.sample(rng);
44 x2 = uniform.sample(rng);
45 sum = x1 * x1 + x2 * x2;
46 if sum < 1. {
47 break;
48 }
49 }
50 let diff = x1 * x1 - x2 * x2;
51 [diff / sum, 2. * x1 * x2 / sum]
52 }
53 }
54
55 #[cfg(test)]
56 mod tests {
57 use super::UnitCircle;
58 use crate::distributions::Distribution;
59
60 /// Assert that two numbers are almost equal to each other.
61 ///
62 /// On panic, this macro will print the values of the expressions with their
63 /// debug representations.
64 macro_rules! assert_almost_eq {
65 ($a:expr, $b:expr, $prec:expr) => {
66 let diff = ($a - $b).abs();
67 if diff > $prec {
68 panic!(format!(
69 "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \
70 (left: `{}`, right: `{}`)",
71 diff, $prec, $a, $b
72 ));
73 }
74 };
75 }
76
77 #[test]
78 fn norm() {
79 let mut rng = crate::test::rng(1);
80 let dist = UnitCircle::new();
81 for _ in 0..1000 {
82 let x = dist.sample(&mut rng);
83 assert_almost_eq!(x[0] * x[0] + x[1] * x[1], 1., 1e-15);
84 }
85 }
86
87 #[test]
88 fn value_stability() {
89 let mut rng = crate::test::rng(2);
90 let expected = [
91 [-0.9965658683520504, -0.08280380447614634],
92 [-0.9790853270389644, -0.20345004884984505],
93 [-0.8449189758898707, 0.5348943112253227],
94 ];
95 let samples = [
96 UnitCircle.sample(&mut rng),
97 UnitCircle.sample(&mut rng),
98 UnitCircle.sample(&mut rng),
99 ];
100 assert_eq!(samples, expected);
101 }
102 }