malachite_base/unsigned_vector/random/mod.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::num::basic::unsigneds::PrimitiveUnsigned;
10use crate::num::random::geometric::GeometricRandomNaturalValues;
11use crate::num::random::striped::{StripedRandomUnsignedBitChunks, striped_random_unsigneds};
12use crate::num::random::{RandomPrimitiveInts, random_primitive_ints};
13use crate::random::Seed;
14use crate::unsigned_vector::UnsignedVector;
15use crate::vecs::random::{
16 RandomFixedLengthVecsFromSingle, RandomVecs, random_vecs, random_vecs_fixed_length_from_single,
17};
18use alloc::vec::Vec;
19
20/// Generates random [`UnsignedVector`]s from an iterator of [`Vec`]s.
21///
22/// This `struct` is created by [`random_unsigned_vectors_from_iterator`],
23/// [`random_unsigned_vectors_with_dimension_from_iterator`], [`random_unsigned_vectors`],
24/// [`random_unsigned_vectors_with_dimension`], [`striped_random_unsigned_vectors`], and
25/// [`striped_random_unsigned_vectors_with_dimension`]; see their documentation for more.
26#[derive(Clone, Debug)]
27pub struct RandomUnsignedVectors<I>(I);
28
29impl<T: PrimitiveUnsigned, I: Iterator<Item = Vec<T>>> Iterator for RandomUnsignedVectors<I> {
30 type Item = UnsignedVector<T>;
31
32 #[inline]
33 fn next(&mut self) -> Option<UnsignedVector<T>> {
34 self.0.next().map(|elements| UnsignedVector { elements })
35 }
36}
37
38/// Generates random [`UnsignedVector`]s whose elements come from an iterator.
39///
40/// `xs_gen` is given a seed derived from `seed` and produces the iterator of elements; each vector
41/// takes its elements, in order, from that iterator. This allows any distribution of elements, for
42/// example one with a bounded number of bits. The dimensions are sampled from a geometric
43/// distribution with mean `mean_length_numerator / mean_length_denominator`, so the 0-dimensional
44/// vector is generated with the probability that that distribution gives to 0.
45///
46/// The iterator produced by `xs_gen` must be infinite, and so is the output.
47///
48/// # Worst-case complexity per iteration
49/// $T(i) = O(n T^\prime(i))$
50///
51/// $M(i) = O(n M^\prime(i))$
52///
53/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
54/// $M^\prime$ are the time and memory functions of the iterator produced by `xs_gen`, and $n$ is
55/// the dimension of the $i$th output.
56///
57/// # Panics
58/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or if, after being
59/// reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
60///
61/// # Examples
62/// The elements here are [`u8`]s from 0 to 15.
63/// ```
64/// use malachite_base::iterators::prefix_to_string;
65/// use malachite_base::num::random::random_unsigned_inclusive_range;
66/// use malachite_base::random::EXAMPLE_SEED;
67/// use malachite_base::unsigned_vector::random::random_unsigned_vectors_from_iterator;
68///
69/// assert_eq!(
70/// prefix_to_string(
71/// random_unsigned_vectors_from_iterator(
72/// EXAMPLE_SEED,
73/// &|seed| random_unsigned_inclusive_range::<u8>(seed, 0, 15),
74/// 2,
75/// 1
76/// ),
77/// 5
78/// ),
79/// "[(5, 5, 11, 0, 8, 8), (8), (12, 11, 14, 6, 8, 11, 12, 15), (13), (6, 2, 11, 14, 9, 13, \
80/// 1, 11, 2, 10, 0, 2, 6, 10), ...]"
81/// );
82/// ```
83#[inline]
84pub fn random_unsigned_vectors_from_iterator<T: PrimitiveUnsigned, I: Iterator<Item = T>>(
85 seed: Seed,
86 xs_gen: &dyn Fn(Seed) -> I,
87 mean_length_numerator: u64,
88 mean_length_denominator: u64,
89) -> RandomUnsignedVectors<RandomVecs<T, GeometricRandomNaturalValues<u64>, I>> {
90 RandomUnsignedVectors(random_vecs(
91 seed,
92 xs_gen,
93 mean_length_numerator,
94 mean_length_denominator,
95 ))
96}
97
98/// Generates random [`UnsignedVector`]s of a given dimension whose elements come from an iterator.
99///
100/// Each vector takes its `dimension` elements, in order, from `xs`. This allows any distribution of
101/// elements, for example one with a bounded number of bits. If `dimension` is 0, the output
102/// consists of the 0-dimensional vector, repeated.
103///
104/// `xs` must be infinite, and so is the output.
105///
106/// # Worst-case complexity per iteration
107/// $T(i) = O(n T^\prime(i))$
108///
109/// $M(i) = O(n M^\prime(i))$
110///
111/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
112/// $M^\prime$ are the time and memory functions of `xs`, and $n$ is `dimension`.
113///
114/// # Examples
115/// The elements here are [`u8`]s from 0 to 15.
116/// ```
117/// use malachite_base::iterators::prefix_to_string;
118/// use malachite_base::num::random::random_unsigned_inclusive_range;
119/// use malachite_base::random::EXAMPLE_SEED;
120/// use malachite_base::unsigned_vector::random::*;
121///
122/// assert_eq!(
123/// prefix_to_string(
124/// random_unsigned_vectors_with_dimension_from_iterator(
125/// 3,
126/// random_unsigned_inclusive_range::<u8>(EXAMPLE_SEED, 0, 15)
127/// ),
128/// 5
129/// ),
130/// "[(1, 7, 15), (14, 5, 4), (12, 6, 4), (14, 2, 13), (8, 10, 1), ...]"
131/// );
132/// ```
133#[inline]
134pub const fn random_unsigned_vectors_with_dimension_from_iterator<
135 T: PrimitiveUnsigned,
136 I: Iterator<Item = T>,
137>(
138 dimension: u64,
139 xs: I,
140) -> RandomUnsignedVectors<RandomFixedLengthVecsFromSingle<I>> {
141 RandomUnsignedVectors(random_vecs_fixed_length_from_single(dimension, xs))
142}
143
144/// Generates random [`UnsignedVector`]s.
145///
146/// The elements are sampled from [`random_primitive_ints`], so each is uniform over its whole
147/// range. The dimensions are sampled from a geometric distribution with mean `mean_length_numerator
148/// / mean_length_denominator`, so the 0-dimensional vector is generated with the probability that
149/// that distribution gives to 0.
150///
151/// The output length is infinite.
152///
153/// # Worst-case complexity per iteration
154/// $T(i) = O(n)$
155///
156/// $M(i) = O(n)$
157///
158/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, and $n$ is the
159/// dimension of the $i$th output.
160///
161/// # Panics
162/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or if, after being
163/// reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
164///
165/// # Examples
166/// ```
167/// use malachite_base::iterators::prefix_to_string;
168/// use malachite_base::random::EXAMPLE_SEED;
169/// use malachite_base::unsigned_vector::random::random_unsigned_vectors;
170///
171/// assert_eq!(
172/// prefix_to_string(random_unsigned_vectors::<u8>(EXAMPLE_SEED, 2, 1), 5),
173/// "[(85, 11, 136, 200, 235, 134), (203), (223, 38, 235, 217, 177, 162, 32, 166), (234), \
174/// (30, 218, 90, 106, 9, 216, 204, 151, 213, 97, 253, 78, 91, 39), ...]"
175/// );
176/// ```
177#[inline]
178pub fn random_unsigned_vectors<T: PrimitiveUnsigned>(
179 seed: Seed,
180 mean_length_numerator: u64,
181 mean_length_denominator: u64,
182) -> RandomUnsignedVectors<RandomVecs<T, GeometricRandomNaturalValues<u64>, RandomPrimitiveInts<T>>>
183{
184 random_unsigned_vectors_from_iterator(
185 seed,
186 &random_primitive_ints,
187 mean_length_numerator,
188 mean_length_denominator,
189 )
190}
191
192/// Generates random [`UnsignedVector`]s of a given dimension.
193///
194/// The elements are sampled from [`random_primitive_ints`], so each is uniform over its whole
195/// range.
196///
197/// If `dimension` is 0, the output consists of the 0-dimensional vector, repeated.
198///
199/// The output length is infinite.
200///
201/// # Worst-case complexity per iteration
202/// $T(i) = O(n)$
203///
204/// $M(i) = O(n)$
205///
206/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, and $n$ is
207/// `dimension`.
208///
209/// # Examples
210/// ```
211/// use malachite_base::iterators::prefix_to_string;
212/// use malachite_base::random::EXAMPLE_SEED;
213/// use malachite_base::unsigned_vector::random::random_unsigned_vectors_with_dimension;
214///
215/// assert_eq!(
216/// prefix_to_string(
217/// random_unsigned_vectors_with_dimension::<u8>(EXAMPLE_SEED, 3),
218/// 5
219/// ),
220/// "[(113, 239, 69), (108, 228, 210), (168, 161, 87), (32, 110, 83), (188, 34, 89), ...]"
221/// );
222/// ```
223#[inline]
224pub fn random_unsigned_vectors_with_dimension<T: PrimitiveUnsigned>(
225 seed: Seed,
226 dimension: u64,
227) -> RandomUnsignedVectors<RandomFixedLengthVecsFromSingle<RandomPrimitiveInts<T>>> {
228 random_unsigned_vectors_with_dimension_from_iterator(dimension, random_primitive_ints(seed))
229}
230
231/// Generates random [`UnsignedVector`]s with striped elements.
232///
233/// The elements are sampled from [`striped_random_unsigneds`], with a mean run length of
234/// `mean_stripe_numerator / mean_stripe_denominator`. A striped element is one whose bits come in
235/// long runs, which is what makes the carries and borrows of an arithmetic test interesting.
236///
237/// The dimensions are sampled from a geometric distribution with mean `mean_length_numerator /
238/// mean_length_denominator`, so the 0-dimensional vector is generated with the probability that
239/// that distribution gives to 0.
240///
241/// The output length is infinite.
242///
243/// # Worst-case complexity per iteration
244/// $T(i) = O(n)$
245///
246/// $M(i) = O(n)$
247///
248/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, and $n$ is the
249/// dimension of the $i$th output.
250///
251/// # Panics
252/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
253/// mean_stripe_denominator`, if `mean_length_numerator` or `mean_length_denominator` are zero, or
254/// if, after being reduced to lowest terms, the sum of those two is greater than or equal to
255/// $2^{64}$.
256///
257/// # Examples
258/// ```
259/// use malachite_base::iterators::prefix_to_string;
260/// use malachite_base::random::EXAMPLE_SEED;
261/// use malachite_base::unsigned_vector::random::striped_random_unsigned_vectors;
262///
263/// assert_eq!(
264/// prefix_to_string(
265/// striped_random_unsigned_vectors::<u8>(EXAMPLE_SEED, 4, 1, 2, 1),
266/// 5
267/// ),
268/// "[(255, 130, 152, 6, 62, 119), (1), (128, 203, 3, 30, 7, 0, 24, 63), (192), \
269/// (30, 0, 240, 195, 248, 56, 231, 7, 193, 194, 96, 126, 253, 119), ...]"
270/// );
271/// ```
272#[inline]
273pub fn striped_random_unsigned_vectors<T: PrimitiveUnsigned>(
274 seed: Seed,
275 mean_stripe_numerator: u64,
276 mean_stripe_denominator: u64,
277 mean_length_numerator: u64,
278 mean_length_denominator: u64,
279) -> RandomUnsignedVectors<
280 RandomVecs<T, GeometricRandomNaturalValues<u64>, StripedRandomUnsignedBitChunks<T>>,
281> {
282 random_unsigned_vectors_from_iterator(
283 seed,
284 &|seed_2| striped_random_unsigneds(seed_2, mean_stripe_numerator, mean_stripe_denominator),
285 mean_length_numerator,
286 mean_length_denominator,
287 )
288}
289
290/// Generates random [`UnsignedVector`]s of a given dimension, with striped elements.
291///
292/// The elements are striped, as they are in [`striped_random_unsigned_vectors`].
293///
294/// If `dimension` is 0, the output consists of the 0-dimensional vector, repeated.
295///
296/// The output length is infinite.
297///
298/// # Worst-case complexity per iteration
299/// $T(i) = O(n)$
300///
301/// $M(i) = O(n)$
302///
303/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, and $n$ is
304/// `dimension`.
305///
306/// # Panics
307/// Panics if `mean_stripe_denominator` is zero or if `mean_stripe_numerator <
308/// mean_stripe_denominator`.
309///
310/// # Examples
311/// ```
312/// use malachite_base::iterators::prefix_to_string;
313/// use malachite_base::random::EXAMPLE_SEED;
314/// use malachite_base::unsigned_vector::random::striped_random_unsigned_vectors_with_dimension;
315///
316/// assert_eq!(
317/// prefix_to_string(
318/// striped_random_unsigned_vectors_with_dimension::<u8>(EXAMPLE_SEED, 3, 4, 1),
319/// 5
320/// ),
321/// "[(1, 76, 127), (195, 0, 128), (15, 118, 0), (248, 255, 253), (121, 0, 240), ...]"
322/// );
323/// ```
324#[inline]
325pub fn striped_random_unsigned_vectors_with_dimension<T: PrimitiveUnsigned>(
326 seed: Seed,
327 dimension: u64,
328 mean_stripe_numerator: u64,
329 mean_stripe_denominator: u64,
330) -> RandomUnsignedVectors<RandomFixedLengthVecsFromSingle<StripedRandomUnsignedBitChunks<T>>> {
331 random_unsigned_vectors_with_dimension_from_iterator(
332 dimension,
333 striped_random_unsigneds(seed, mean_stripe_numerator, mean_stripe_denominator),
334 )
335}