random_number/
random_fill_functions.rs

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/// Generate random values in the range [`min`, `max_exclusive`) with a new lazily-initialized thread-local random number generator.
18///
19/// Panics if `min >= max_exclusive`.
20#[inline]
21pub fn random_fill_exclusively<X: SampleUniform, B1: SampleBorrow<X>, B2: SampleBorrow<X>>(
22    out: &mut [X],
23    min: B1,
24    max_exclusive: B2,
25) {
26    random_fill_exclusively_with_rng(out, min, max_exclusive, &mut thread_rng())
27}
28
29/// Generate random values in the range [`min`, `max_exclusive`) with an existing random number generator.
30///
31/// Panics if `min >= max_exclusive`.
32#[inline]
33pub fn random_fill_exclusively_with_rng<
34    X: SampleUniform,
35    B1: SampleBorrow<X>,
36    B2: SampleBorrow<X>,
37    T: Rng,
38>(
39    out: &mut [X],
40    min: B1,
41    max_exclusive: B2,
42    rng: &mut T,
43) {
44    let uniform = Uniform::new(min, max_exclusive);
45
46    for x in out.iter_mut() {
47        *x = uniform.sample(rng);
48    }
49}
50
51/// Generate random values in the range [`min`, `max_inclusive`] with a new lazily-initialized thread-local random number generator.
52///
53/// Panics if `min > max_inclusive`.
54#[inline]
55pub fn random_fill_inclusively<X: SampleUniform, B1: SampleBorrow<X>, B2: SampleBorrow<X>>(
56    out: &mut [X],
57    min: B1,
58    max_inclusive: B2,
59) {
60    random_fill_inclusively_with_rng(out, min, max_inclusive, &mut thread_rng());
61}
62
63/// Generate random values in the range [`min`, `max_inclusive`] with an existing random number generator.
64///
65/// Panics if `min > max_inclusive`.
66#[inline]
67pub fn random_fill_inclusively_with_rng<
68    X: SampleUniform,
69    B1: SampleBorrow<X>,
70    B2: SampleBorrow<X>,
71    T: Rng,
72>(
73    out: &mut [X],
74    min: B1,
75    max_inclusive: B2,
76    rng: &mut T,
77) {
78    let uniform = Uniform::new_inclusive(min, max_inclusive);
79    let mut random_iter = uniform.sample_iter(rng);
80
81    for x in out.iter_mut() {
82        *x = random_iter.next().unwrap();
83    }
84}
85
86/// Generate random values in the range [`a`, `b`] or [`b`, `a`] with a new lazily-initialized thread-local random number generator.
87///
88/// Panics if a and b can not be compared.
89#[inline]
90pub fn random_fill_inclusively_cmp<X: SampleUniform + Ord + Clone, B: SampleBorrow<X>>(
91    out: &mut [X],
92    a: B,
93    b: B,
94) {
95    random_fill_inclusively_cmp_with_rng(out, a, b, &mut thread_rng());
96}
97
98/// Generate random values in the range [`a`, `b`] or [`b`, `a`] with an existing random number generator.
99#[inline]
100pub fn random_fill_inclusively_cmp_with_rng<
101    X: SampleUniform + Ord + Clone,
102    B: SampleBorrow<X>,
103    T: Rng,
104>(
105    out: &mut [X],
106    a: B,
107    b: B,
108    rng: &mut T,
109) {
110    match a.borrow().cmp(b.borrow()) {
111        Ordering::Greater => random_fill_inclusively_with_rng(out, b, a, rng),
112        Ordering::Equal => {
113            for x in out.iter_mut() {
114                *x = a.borrow().clone();
115            }
116        },
117        Ordering::Less => random_fill_inclusively_with_rng(out, a, b, rng),
118    }
119}
120
121/// Generate random values in the range of the output type with a new lazily-initialized thread-local random number generator.
122#[inline]
123pub fn random_fill<X: SampleUniform + Bounded>(out: &mut [X]) {
124    random_fill_with_rng(out, &mut thread_rng())
125}
126
127/// Generate random values in the range of the output type with an existing random number generator.
128#[inline]
129pub fn random_fill_with_rng<X: SampleUniform + Bounded, T: Rng>(out: &mut [X], rng: &mut T) {
130    random_fill_inclusively_with_rng(out, X::min_value(), X::max_value(), rng);
131}
132
133/// Generate random values in the range [`min`, `Bounded::max_value()`] with a new lazily-initialized thread-local random number generator.
134#[inline]
135pub fn random_fill_at_least<X: SampleUniform + Bounded, B: SampleBorrow<X>>(out: &mut [X], min: B) {
136    random_fill_at_least_with_rng(out, min, &mut thread_rng());
137}
138
139/// Generate random values in the range [`min`, `X::max_value()`] with an existing random number generator.
140#[inline]
141pub fn random_fill_at_least_with_rng<X: SampleUniform + Bounded, B: SampleBorrow<X>, T: Rng>(
142    out: &mut [X],
143    min: B,
144    rng: &mut T,
145) {
146    random_fill_inclusively_with_rng(out, min, X::max_value(), rng);
147}
148
149/// Generate random values in the range [`X::min_value()`, `max_inclusive`] with a new lazily-initialized thread-local random number generator.
150#[inline]
151pub fn random_fill_at_most<X: SampleUniform + Bounded, B: SampleBorrow<X>>(
152    out: &mut [X],
153    max_inclusive: B,
154) {
155    random_fill_at_most_with_rng(out, max_inclusive, &mut thread_rng());
156}
157
158/// Generate random values in the range [`X::min_value()`, `max_inclusive`] with an existing random number generator.
159#[inline]
160pub fn random_fill_at_most_with_rng<X: SampleUniform + Bounded, B: SampleBorrow<X>, T: Rng>(
161    out: &mut [X],
162    max_inclusive: B,
163    rng: &mut T,
164) {
165    random_fill_inclusively_with_rng(out, X::min_value(), max_inclusive, rng);
166}
167
168/// Generate random values in the range [`X::min_value()`, `max_exclusive`) with a new lazily-initialized thread-local random number generator.
169///
170/// Panics if X::min_value() == max_exclusive.
171#[inline]
172pub fn random_fill_at_most_exclusively<X: SampleUniform + Bounded, B: SampleBorrow<X>>(
173    out: &mut [X],
174    max_exclusive: B,
175) {
176    random_fill_at_most_exclusively_with_rng(out, max_exclusive, &mut thread_rng());
177}
178
179/// Generate random values in the range [`X::min_value()`, `max_exclusive`) with an existing random number generator.
180///
181/// Panics if X::min_value() == max_exclusive.
182#[inline]
183pub fn random_fill_at_most_exclusively_with_rng<
184    X: SampleUniform + Bounded,
185    B: SampleBorrow<X>,
186    T: Rng,
187>(
188    out: &mut [X],
189    max_exclusive: B,
190    rng: &mut T,
191) {
192    random_fill_exclusively_with_rng(out, X::min_value(), max_exclusive, rng);
193}
194
195/// Generate random values in a specific range with a new lazily-initialized thread-local random number generator.
196///
197/// Panics if the start bound is exclusive.
198#[inline]
199pub fn random_fill_ranged<X: SampleUniform + Bounded, R: RangeBounds<X>>(out: &mut [X], range: R) {
200    random_fill_ranged_with_rng(out, range, &mut thread_rng())
201}
202
203/// Generate random values in a specific range with an existing random number generator.
204///
205/// Panics if the start bound is exclusive.
206#[inline]
207pub fn random_fill_ranged_with_rng<X: SampleUniform + Bounded, R: RangeBounds<X>, T: Rng>(
208    out: &mut [X],
209    range: R,
210    rng: &mut T,
211) {
212    let start = range.start_bound();
213    let end = range.end_bound();
214
215    match start {
216        Bound::Excluded(_) => {
217            panic!("random_fill_ranged_with_rng called with a start bound which is exclusive")
218        },
219        Bound::Included(min) => match end {
220            Bound::Excluded(max_exclusive) => {
221                random_fill_exclusively_with_rng(out, min, max_exclusive, rng)
222            },
223            Bound::Included(max_inclusive) => {
224                random_fill_inclusively_with_rng(out, min, max_inclusive, rng)
225            },
226            Bound::Unbounded => random_fill_at_least_with_rng(out, min, rng),
227        },
228        Bound::Unbounded => match end {
229            Bound::Excluded(max_exclusive) => {
230                random_fill_at_most_exclusively_with_rng(out, max_exclusive, rng)
231            },
232            Bound::Included(max_inclusive) => random_fill_at_most_with_rng(out, max_inclusive, rng),
233            Bound::Unbounded => random_fill_with_rng(out, rng),
234        },
235    }
236}