1use std::{
2 cmp::Ordering,
3 ops::{Bound, RangeBounds},
4};
5
6use crate::{
7 rand::{
8 distributions::{
9 uniform::{SampleBorrow, SampleUniform, Uniform},
10 Distribution,
11 },
12 thread_rng, Rng,
13 },
14 Bounded,
15};
16
17#[inline]
21pub fn random_exclusively<X: SampleUniform, B1: SampleBorrow<X>, B2: SampleBorrow<X>>(
22 min: B1,
23 max_exclusive: B2,
24) -> X {
25 random_exclusively_with_rng(min, max_exclusive, &mut thread_rng())
26}
27
28#[inline]
32pub fn random_exclusively_with_rng<
33 X: SampleUniform,
34 B1: SampleBorrow<X>,
35 B2: SampleBorrow<X>,
36 T: Rng,
37>(
38 min: B1,
39 max_exclusive: B2,
40 rng: &mut T,
41) -> X {
42 let uniform = Uniform::new(min, max_exclusive);
43
44 uniform.sample(rng)
45}
46
47#[inline]
51pub fn random_inclusively<X: SampleUniform, B1: SampleBorrow<X>, B2: SampleBorrow<X>>(
52 min: B1,
53 max_inclusive: B2,
54) -> X {
55 random_inclusively_with_rng(min, max_inclusive, &mut thread_rng())
56}
57
58#[inline]
62pub fn random_inclusively_with_rng<
63 X: SampleUniform,
64 B1: SampleBorrow<X>,
65 B2: SampleBorrow<X>,
66 T: Rng,
67>(
68 min: B1,
69 max_inclusive: B2,
70 rng: &mut T,
71) -> X {
72 Uniform::new_inclusive(min, max_inclusive).sample(rng)
73}
74
75#[inline]
79pub fn random_inclusively_cmp<X: SampleUniform + Ord + Clone, B: SampleBorrow<X>>(a: B, b: B) -> X {
80 random_inclusively_cmp_with_rng(a, b, &mut thread_rng())
81}
82
83#[inline]
85pub fn random_inclusively_cmp_with_rng<
86 X: SampleUniform + Ord + Clone,
87 B: SampleBorrow<X>,
88 T: Rng,
89>(
90 a: B,
91 b: B,
92 rng: &mut T,
93) -> X {
94 match a.borrow().cmp(b.borrow()) {
95 Ordering::Greater => random_inclusively_with_rng(b, a, rng),
96 Ordering::Equal => a.borrow().clone(),
97 Ordering::Less => random_inclusively_with_rng(a, b, rng),
98 }
99}
100
101#[inline]
103pub fn random<X: SampleUniform + Bounded>() -> X {
104 random_with_rng(&mut thread_rng())
105}
106
107#[inline]
109pub fn random_with_rng<X: SampleUniform + Bounded, T: Rng>(rng: &mut T) -> X {
110 random_inclusively_with_rng(X::min_value(), X::max_value(), rng)
111}
112
113#[inline]
115pub fn random_at_least<X: SampleUniform + Bounded, B: SampleBorrow<X>>(min: B) -> X {
116 random_at_least_with_rng(min, &mut thread_rng())
117}
118
119#[inline]
121pub fn random_at_least_with_rng<X: SampleUniform + Bounded, B: SampleBorrow<X>, T: Rng>(
122 min: B,
123 rng: &mut T,
124) -> X {
125 random_inclusively_with_rng(min, X::max_value(), rng)
126}
127
128#[inline]
130pub fn random_at_most<X: SampleUniform + Bounded, B: SampleBorrow<X>>(max_inclusive: B) -> X {
131 random_at_most_with_rng(max_inclusive, &mut thread_rng())
132}
133
134#[inline]
136pub fn random_at_most_with_rng<X: SampleUniform + Bounded, B: SampleBorrow<X>, T: Rng>(
137 max_inclusive: B,
138 rng: &mut T,
139) -> X {
140 random_inclusively_with_rng(X::min_value(), max_inclusive, rng)
141}
142
143#[inline]
147pub fn random_at_most_exclusively<X: SampleUniform + Bounded, B: SampleBorrow<X>>(
148 max_exclusive: B,
149) -> X {
150 random_at_most_exclusively_with_rng(max_exclusive, &mut thread_rng())
151}
152
153#[inline]
157pub fn random_at_most_exclusively_with_rng<
158 X: SampleUniform + Bounded,
159 B: SampleBorrow<X>,
160 T: Rng,
161>(
162 max_exclusive: B,
163 rng: &mut T,
164) -> X {
165 random_exclusively_with_rng(X::min_value(), max_exclusive, rng)
166}
167
168#[inline]
172pub fn random_ranged<X: SampleUniform + Bounded, R: RangeBounds<X>>(range: R) -> X {
173 random_ranged_with_rng(range, &mut thread_rng())
174}
175
176#[inline]
180pub fn random_ranged_with_rng<X: SampleUniform + Bounded, R: RangeBounds<X>, T: Rng>(
181 range: R,
182 rng: &mut T,
183) -> X {
184 let start = range.start_bound();
185 let end = range.end_bound();
186
187 match start {
188 Bound::Excluded(_) => {
189 panic!("random_ranged_with_rng called with a start bound which is exclusive")
190 },
191 Bound::Included(min) => match end {
192 Bound::Excluded(max_exclusive) => random_exclusively_with_rng(min, max_exclusive, rng),
193 Bound::Included(max_inclusive) => random_inclusively_with_rng(min, max_inclusive, rng),
194 Bound::Unbounded => random_at_least_with_rng(min, rng),
195 },
196 Bound::Unbounded => match end {
197 Bound::Excluded(max_exclusive) => {
198 random_at_most_exclusively_with_rng(max_exclusive, rng)
199 },
200 Bound::Included(max_inclusive) => random_at_most_with_rng(max_inclusive, rng),
201 Bound::Unbounded => random_with_rng(rng),
202 },
203 }
204}