malachite_nz/integer_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::integer::Integer;
10use crate::integer::random::{
11 RandomIntegers, StripedRandomIntegers, random_integers, striped_random_integers,
12};
13use crate::integer_vector::IntegerVector;
14use alloc::vec::Vec;
15use malachite_base::num::random::geometric::{
16 GeometricRandomNaturalValues, GeometricRandomSigneds,
17};
18use malachite_base::random::Seed;
19use malachite_base::vecs::random::{
20 RandomFixedLengthVecsFromSingle, RandomVecs, random_vecs, random_vecs_fixed_length_from_single,
21};
22
23/// Generates random [`IntegerVector`]s from an iterator of [`Vec`]s of [`Integer`]s.
24///
25/// This `struct` is created by [`random_integer_vectors_from_iterator`],
26/// [`random_integer_vectors_with_dimension_from_iterator`], [`random_integer_vectors`],
27/// [`random_integer_vectors_with_dimension`], [`striped_random_integer_vectors`], and
28/// [`striped_random_integer_vectors_with_dimension`]; see their documentation for more.
29#[derive(Clone, Debug)]
30pub struct RandomIntegerVectors<I: Iterator<Item = Vec<Integer>>>(I);
31
32impl<I: Iterator<Item = Vec<Integer>>> Iterator for RandomIntegerVectors<I> {
33 type Item = IntegerVector;
34
35 #[inline]
36 fn next(&mut self) -> Option<IntegerVector> {
37 self.0.next().map(|elements| IntegerVector { elements })
38 }
39}
40
41/// The elements that the unstriped [`IntegerVector`] generators draw on.
42pub type RandomVectorElements = RandomIntegers<GeometricRandomSigneds<i64>>;
43
44/// The elements that the striped [`IntegerVector`] generators draw on.
45pub type StripedRandomVectorElements = StripedRandomIntegers<GeometricRandomSigneds<i64>>;
46
47/// Generates random [`IntegerVector`]s whose elements come from an iterator.
48///
49/// `xs_gen` is given a seed derived from `seed` and produces the iterator of elements; each vector
50/// takes its elements, in order, from that iterator. This allows any distribution of elements, for
51/// example one with a bounded number of bits. The dimensions are sampled from a geometric
52/// distribution with mean `mean_length_numerator / mean_length_denominator`, so the 0-dimensional
53/// vector is generated with the probability that that distribution gives to 0.
54///
55/// The iterator produced by `xs_gen` must be infinite, and so is the output.
56///
57/// # Worst-case complexity per iteration
58/// $T(i) = O(n T^\prime(i))$
59///
60/// $M(i) = O(n M^\prime(i))$
61///
62/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
63/// $M^\prime$ are the time and memory functions of the iterator produced by `xs_gen`, and $n$ is
64/// the dimension of the $i$th output.
65///
66/// # Panics
67/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or if, after being
68/// reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
69///
70/// # Examples
71/// The elements here are [`Integer`]s from $-8$ to $8$.
72/// ```
73/// use malachite_base::iterators::prefix_to_string;
74/// use malachite_base::random::EXAMPLE_SEED;
75/// use malachite_nz::integer::Integer;
76/// use malachite_nz::integer::random::uniform_random_integer_inclusive_range;
77/// use malachite_nz::integer_vector::random::random_integer_vectors_from_iterator;
78///
79/// assert_eq!(
80/// prefix_to_string(
81/// random_integer_vectors_from_iterator(
82/// EXAMPLE_SEED,
83/// &|seed| uniform_random_integer_inclusive_range(
84/// seed,
85/// Integer::from(-8),
86/// Integer::from(8)
87/// ),
88/// 2,
89/// 1
90/// ),
91/// 5
92/// ),
93/// "[(-2, 2, 5, -3, 2, 1), (8), (1, -5, 6, 7, -8, -5, 7, -4), (7), (6, -5, 8, 3, 4, -3, -1, \
94/// 1, -7, 2, -6, 6, -2, 8), ...]"
95/// );
96/// ```
97#[inline]
98pub fn random_integer_vectors_from_iterator<I: Iterator<Item = Integer>>(
99 seed: Seed,
100 xs_gen: &dyn Fn(Seed) -> I,
101 mean_length_numerator: u64,
102 mean_length_denominator: u64,
103) -> RandomIntegerVectors<RandomVecs<Integer, GeometricRandomNaturalValues<u64>, I>> {
104 RandomIntegerVectors(random_vecs(
105 seed,
106 xs_gen,
107 mean_length_numerator,
108 mean_length_denominator,
109 ))
110}
111
112/// Generates random [`IntegerVector`]s of a given dimension whose elements come from an iterator.
113///
114/// Each vector takes its `dimension` elements, in order, from `xs`. This allows any distribution of
115/// elements, for example one with a bounded number of bits. If `dimension` is 0, the output
116/// consists of the 0-dimensional vector, repeated.
117///
118/// `xs` must be infinite, and so is the output.
119///
120/// # Worst-case complexity per iteration
121/// $T(i) = O(n T^\prime(i))$
122///
123/// $M(i) = O(n M^\prime(i))$
124///
125/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
126/// $M^\prime$ are the time and memory functions of `xs`, and $n$ is `dimension`.
127///
128/// # Examples
129/// The elements here are [`Integer`]s from $-8$ to $8$.
130/// ```
131/// use malachite_base::iterators::prefix_to_string;
132/// use malachite_base::random::EXAMPLE_SEED;
133/// use malachite_nz::integer::Integer;
134/// use malachite_nz::integer::random::uniform_random_integer_inclusive_range;
135/// use malachite_nz::integer_vector::random::random_integer_vectors_with_dimension_from_iterator;
136///
137/// assert_eq!(
138/// prefix_to_string(
139/// random_integer_vectors_with_dimension_from_iterator(
140/// 3,
141/// uniform_random_integer_inclusive_range(
142/// EXAMPLE_SEED,
143/// Integer::from(-8),
144/// Integer::from(8)
145/// )
146/// ),
147/// 5
148/// ),
149/// "[(-1, 1, 0), (3, 6, 3), (-7, -1, -7), (-2, -2, -2), (-1, -3, 4), ...]"
150/// );
151/// ```
152#[inline]
153pub const fn random_integer_vectors_with_dimension_from_iterator<I: Iterator<Item = Integer>>(
154 dimension: u64,
155 xs: I,
156) -> RandomIntegerVectors<RandomFixedLengthVecsFromSingle<I>> {
157 RandomIntegerVectors(random_vecs_fixed_length_from_single(dimension, xs))
158}
159
160/// Generates random [`IntegerVector`]s.
161///
162/// The elements are sampled from [`random_integers`], with a mean bit count of `mean_bits_numerator
163/// / mean_bits_denominator`. The dimensions are sampled from a geometric distribution with mean
164/// `mean_length_numerator / mean_length_denominator`, so the 0-dimensional vector is generated with
165/// the probability that that distribution gives to 0.
166///
167/// The output length is infinite.
168///
169/// # Worst-case complexity per iteration
170/// $T(i) = O(nb)$
171///
172/// $M(i) = O(nb)$
173///
174/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $n$ is the dimension
175/// of the $i$th output, and $b$ is `mean_bits_numerator / mean_bits_denominator`.
176///
177/// # Panics
178/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if `mean_length_numerator`
179/// or `mean_length_denominator` are zero, or if either ratio, after being reduced to lowest terms,
180/// has a numerator and denominator whose sum is greater than or equal to $2^{64}$.
181///
182/// # Examples
183/// ```
184/// use malachite_base::iterators::prefix_to_string;
185/// use malachite_base::random::EXAMPLE_SEED;
186/// use malachite_nz::integer_vector::random::random_integer_vectors;
187///
188/// assert_eq!(
189/// prefix_to_string(random_integer_vectors(EXAMPLE_SEED, 4, 1, 2, 1), 5),
190/// "[(-497, -1, 1, 19, 799, 799), (-1), (66, -10721, 334, 59, -119, -5, 0, -131), (-1), \
191/// (0, 7, -1, 10, 11, -37408, 0, -1, -903, 28, 0, 0, -6, 2), ...]"
192/// );
193/// ```
194#[inline]
195pub fn random_integer_vectors(
196 seed: Seed,
197 mean_bits_numerator: u64,
198 mean_bits_denominator: u64,
199 mean_length_numerator: u64,
200 mean_length_denominator: u64,
201) -> RandomIntegerVectors<
202 RandomVecs<Integer, GeometricRandomNaturalValues<u64>, RandomVectorElements>,
203> {
204 random_integer_vectors_from_iterator(
205 seed,
206 &|seed_2| random_integers(seed_2, mean_bits_numerator, mean_bits_denominator),
207 mean_length_numerator,
208 mean_length_denominator,
209 )
210}
211
212/// Generates random [`IntegerVector`]s of a given dimension.
213///
214/// The elements are sampled from [`random_integers`], with a mean bit count of `mean_bits_numerator
215/// / mean_bits_denominator`.
216///
217/// If `dimension` is 0, the output consists of the 0-dimensional vector, repeated.
218///
219/// The output length is infinite.
220///
221/// # Worst-case complexity per iteration
222/// $T(i) = O(nb)$
223///
224/// $M(i) = O(nb)$
225///
226/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $n$ is `dimension`,
227/// and $b$ is `mean_bits_numerator / mean_bits_denominator`.
228///
229/// # Panics
230/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if, after being reduced
231/// to lowest terms, their sum is greater than or equal to $2^{64}$.
232///
233/// # Examples
234/// ```
235/// use malachite_base::iterators::prefix_to_string;
236/// use malachite_base::random::EXAMPLE_SEED;
237/// use malachite_nz::integer_vector::random::random_integer_vectors_with_dimension;
238///
239/// assert_eq!(
240/// prefix_to_string(
241/// random_integer_vectors_with_dimension(EXAMPLE_SEED, 3, 4, 1),
242/// 5
243/// ),
244/// "[(2, 152, 1), (0, -62, 5282), (0, 28, 4427344568), (79, -11, -7330), \
245/// (-1, -5667523, 1618), ...]"
246/// );
247/// ```
248#[inline]
249pub fn random_integer_vectors_with_dimension(
250 seed: Seed,
251 dimension: u64,
252 mean_bits_numerator: u64,
253 mean_bits_denominator: u64,
254) -> RandomIntegerVectors<RandomFixedLengthVecsFromSingle<RandomVectorElements>> {
255 random_integer_vectors_with_dimension_from_iterator(
256 dimension,
257 random_integers(seed, mean_bits_numerator, mean_bits_denominator),
258 )
259}
260
261/// Generates random [`IntegerVector`]s with striped elements.
262///
263/// The elements are sampled from [`striped_random_integers`]: each element's bit count has mean
264/// `mean_bits_numerator / mean_bits_denominator`, and its bits come in runs whose mean length is
265/// `mean_stripe_numerator / mean_stripe_denominator`. A striped element is one whose bits come in
266/// long runs, which is what makes the carries and borrows of an arithmetic test interesting.
267///
268/// The dimensions are sampled from a geometric distribution with mean `mean_length_numerator /
269/// mean_length_denominator`, so the 0-dimensional vector is generated with the probability that
270/// that distribution gives to 0.
271///
272/// The output length is infinite.
273///
274/// # Worst-case complexity per iteration
275/// $T(i) = O(nb)$
276///
277/// $M(i) = O(nb)$
278///
279/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $n$ is the dimension
280/// of the $i$th output, and $b$ is `mean_bits_numerator / mean_bits_denominator`.
281///
282/// # Panics
283/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
284/// mean_stripe_denominator`, if `mean_bits_numerator`, `mean_bits_denominator`,
285/// `mean_length_numerator`, or `mean_length_denominator` are zero, or if either of the last two
286/// ratios, after being reduced to lowest terms, has a numerator and denominator whose sum is
287/// greater than or equal to $2^{64}$.
288///
289/// # Examples
290/// ```
291/// use malachite_base::iterators::prefix_to_string;
292/// use malachite_base::random::EXAMPLE_SEED;
293/// use malachite_nz::integer_vector::random::striped_random_integer_vectors;
294///
295/// assert_eq!(
296/// prefix_to_string(
297/// striped_random_integer_vectors(EXAMPLE_SEED, 16, 1, 4, 1, 2, 1),
298/// 5
299/// ),
300/// "[(-496, -1, 1, 16, 512, 543), (-1), (127, -10239, 383, 36, -127, -4, 0, -230), (-1), \
301/// (0, 4, -1, 8, 15, -65024, 0, -1, -1023, 16, 0, 0, -7, 3), ...]"
302/// );
303/// ```
304#[inline]
305pub fn striped_random_integer_vectors(
306 seed: Seed,
307 mean_stripe_numerator: u64,
308 mean_stripe_denominator: u64,
309 mean_bits_numerator: u64,
310 mean_bits_denominator: u64,
311 mean_length_numerator: u64,
312 mean_length_denominator: u64,
313) -> RandomIntegerVectors<
314 RandomVecs<Integer, GeometricRandomNaturalValues<u64>, StripedRandomVectorElements>,
315> {
316 random_integer_vectors_from_iterator(
317 seed,
318 &|seed_2| {
319 striped_random_integers(
320 seed_2,
321 mean_stripe_numerator,
322 mean_stripe_denominator,
323 mean_bits_numerator,
324 mean_bits_denominator,
325 )
326 },
327 mean_length_numerator,
328 mean_length_denominator,
329 )
330}
331
332/// Generates random [`IntegerVector`]s of a given dimension, with striped elements.
333///
334/// The elements are striped, as they are in [`striped_random_integer_vectors`].
335///
336/// If `dimension` is 0, the output consists of the 0-dimensional vector, repeated.
337///
338/// The output length is infinite.
339///
340/// # Worst-case complexity per iteration
341/// $T(i) = O(nb)$
342///
343/// $M(i) = O(nb)$
344///
345/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $n$ is `dimension`,
346/// and $b$ is `mean_bits_numerator / mean_bits_denominator`.
347///
348/// # Panics
349/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
350/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if,
351/// after being reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
352///
353/// # Examples
354/// ```
355/// use malachite_base::iterators::prefix_to_string;
356/// use malachite_base::random::EXAMPLE_SEED;
357/// use malachite_nz::integer_vector::random::striped_random_integer_vectors_with_dimension;
358///
359/// assert_eq!(
360/// prefix_to_string(
361/// striped_random_integer_vectors_with_dimension(EXAMPLE_SEED, 3, 16, 1, 4, 1),
362/// 5
363/// ),
364/// "[(2, 128, 1), (0, -32, 4096), (0, 31, 6442451424), (127, -8, -6145), \
365/// (-1, -7864320, 1024), ...]"
366/// );
367/// ```
368#[inline]
369pub fn striped_random_integer_vectors_with_dimension(
370 seed: Seed,
371 dimension: u64,
372 mean_stripe_numerator: u64,
373 mean_stripe_denominator: u64,
374 mean_bits_numerator: u64,
375 mean_bits_denominator: u64,
376) -> RandomIntegerVectors<RandomFixedLengthVecsFromSingle<StripedRandomVectorElements>> {
377 random_integer_vectors_with_dimension_from_iterator(
378 dimension,
379 striped_random_integers(
380 seed,
381 mean_stripe_numerator,
382 mean_stripe_denominator,
383 mean_bits_numerator,
384 mean_bits_denominator,
385 ),
386 )
387}