Skip to main content

malachite_nz/integer_polynomial/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, random_nonzero_integers,
12    striped_random_integers, striped_random_nonzero_integers,
13};
14use crate::integer_polynomial::IntegerPolynomial;
15use malachite_base::num::random::RandomUnsignedInclusiveRange;
16use malachite_base::num::random::geometric::{
17    GeometricRandomNaturalValues, GeometricRandomNonzeroSigneds, GeometricRandomSigneds,
18};
19use malachite_base::polynomial::Polynomial;
20use malachite_base::random::Seed;
21use malachite_base::vecs::random::{
22    RandomFixedLengthVecsWithLast, RandomVecsWithLast, random_vecs_with_last,
23    random_vecs_with_last_fixed_length, random_vecs_with_last_length_inclusive_range,
24    random_vecs_with_last_min_length,
25};
26
27/// Generates random [`IntegerPolynomial`]s with coefficients from one iterator and leading
28/// coefficients from another.
29///
30/// This `struct` is created by [`random_integer_polynomials_from_iterators`] and the generators
31/// built on it; see their documentation for more.
32#[derive(Clone, Debug)]
33pub struct RandomIntegerPolynomials<
34    I: Iterator<Item = u64>,
35    J: Iterator<Item = Integer>,
36    K: Iterator<Item = Integer>,
37>(RandomVecsWithLast<Integer, I, J, K>);
38
39impl<I: Iterator<Item = u64>, J: Iterator<Item = Integer>, K: Iterator<Item = Integer>> Iterator
40    for RandomIntegerPolynomials<I, J, K>
41{
42    type Item = IntegerPolynomial;
43
44    #[inline]
45    fn next(&mut self) -> Option<IntegerPolynomial> {
46        self.0.next().map(IntegerPolynomial::from_coefficients_asc)
47    }
48}
49
50/// The type of the [`IntegerPolynomial`] generators that draw their coefficients from every
51/// [`Integer`] and their leading coefficients from every nonzero one, with lengths from a geometric
52/// distribution.
53pub type RandomIntegerPolynomialsFromIntegers = RandomIntegerPolynomials<
54    GeometricRandomNaturalValues<u64>,
55    RandomPolynomialCoefficients,
56    RandomPolynomialLeadingCoefficients,
57>;
58
59/// Generates random [`IntegerPolynomial`]s whose coefficients come from one iterator and whose
60/// leading coefficients come from another.
61///
62/// A polynomial is its coefficients, and the only thing that distinguishes them from any other list
63/// of [`Integer`]s is that the last of them may not be zero. Singling out that one coefficient is
64/// therefore all it takes: `xs_gen` supplies every coefficient below the leading one, and `ys_gen`
65/// supplies the leading one.
66///
67/// `ys_gen` should produce no zeros, since a polynomial's leading coefficient is never zero. If it
68/// does, the zeros are trimmed away, and the polynomial has a lower degree than its length
69/// suggests.
70///
71/// The lengths of the polynomials — the number of coefficients, which is one more than the
72/// degree, or zero for the zero polynomial — are sampled from a geometric distribution with a
73/// specified mean $m$, equal to `mean_length_numerator / mean_length_denominator`. $m$ must be
74/// greater than 0.
75///
76/// The iterators produced by `xs_gen` and `ys_gen` must be infinite.
77///
78/// # Worst-case complexity per iteration
79/// $T(i) = O(\ell T^\prime(i))$
80///
81/// $M(i) = O(\ell M^\prime(i))$
82///
83/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
84/// $M^\prime$ are the time and memory functions of the iterators produced by `xs_gen` and `ys_gen`,
85/// and $\ell$ is the number of coefficients of the $i$th output.
86///
87/// # Panics
88/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or if their ratio is
89/// greater than or equal to $2^{64}$.
90///
91/// # Examples
92/// ```
93/// use malachite_base::iterators::prefix_to_string;
94/// use malachite_base::random::EXAMPLE_SEED;
95/// use malachite_nz::integer::random::{random_integers, random_nonzero_integers};
96/// use malachite_nz::integer_polynomial::random::random_integer_polynomials_from_iterators;
97///
98/// assert_eq!(
99///     prefix_to_string(
100///         random_integer_polynomials_from_iterators(
101///             EXAMPLE_SEED,
102///             &|seed| random_integers(seed, 4, 1),
103///             &|seed| random_nonzero_integers(seed, 4, 1),
104///             1,
105///             1,
106///         ),
107///         5
108///     ),
109///     "[14, -2*x-497, 2*x-1, 122*x+1, 1, ...]"
110/// );
111/// ```
112#[inline]
113pub fn random_integer_polynomials_from_iterators<
114    J: Iterator<Item = Integer>,
115    K: Iterator<Item = Integer>,
116>(
117    seed: Seed,
118    xs_gen: &dyn Fn(Seed) -> J,
119    ys_gen: &dyn Fn(Seed) -> K,
120    mean_length_numerator: u64,
121    mean_length_denominator: u64,
122) -> RandomIntegerPolynomials<GeometricRandomNaturalValues<u64>, J, K> {
123    RandomIntegerPolynomials(random_vecs_with_last(
124        seed,
125        xs_gen,
126        ys_gen,
127        mean_length_numerator,
128        mean_length_denominator,
129    ))
130}
131
132/// Generates random [`IntegerPolynomial`]s.
133///
134/// The coefficients are sampled from [`random_integers`] and the leading coefficient from
135/// [`random_nonzero_integers`], both with a mean bit count of `mean_bits_numerator /
136/// mean_bits_denominator`.
137///
138/// The lengths — the number of coefficients, which is one more than the degree, or zero for the
139/// zero polynomial — are sampled from a geometric distribution with mean `mean_length_numerator /
140/// mean_length_denominator`, so the zero polynomial is generated with the probability that that
141/// distribution gives to 0.
142///
143/// # Worst-case complexity per iteration
144/// $T(i) = O(\ell b)$
145///
146/// $M(i) = O(\ell b)$
147///
148/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $\ell$ is the number
149/// of coefficients of the $i$th output, and $b$ is `mean_bits_numerator / mean_bits_denominator`.
150///
151/// # Panics
152/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their ratio is less than
153/// or equal to 1, or if `mean_length_numerator` or `mean_length_denominator` are zero or their
154/// ratio is greater than or equal to $2^{64}$.
155///
156/// # Examples
157/// ```
158/// use malachite_base::iterators::prefix_to_string;
159/// use malachite_base::random::EXAMPLE_SEED;
160/// use malachite_nz::integer_polynomial::random::random_integer_polynomials;
161///
162/// assert_eq!(
163///     prefix_to_string(random_integer_polynomials(EXAMPLE_SEED, 4, 1, 1, 1), 5),
164///     "[14, -2*x-497, 2*x-1, 122*x+1, 1, ...]"
165/// );
166/// ```
167#[inline]
168pub fn random_integer_polynomials(
169    seed: Seed,
170    mean_bits_numerator: u64,
171    mean_bits_denominator: u64,
172    mean_length_numerator: u64,
173    mean_length_denominator: u64,
174) -> RandomIntegerPolynomialsFromIntegers {
175    random_integer_polynomials_from_iterators(
176        seed,
177        &|seed_2| random_integers(seed_2, mean_bits_numerator, mean_bits_denominator),
178        &|seed_2| random_nonzero_integers(seed_2, mean_bits_numerator, mean_bits_denominator),
179        mean_length_numerator,
180        mean_length_denominator,
181    )
182}
183
184/// Generates random [`IntegerPolynomial`]s of a given degree, with coefficients from one iterator
185/// and leading coefficients from another.
186///
187/// This `struct` is created by [`random_integer_polynomials_with_degree`] and
188/// [`striped_random_integer_polynomials_with_degree`]; see their documentation for more.
189#[derive(Clone, Debug)]
190pub struct RandomIntegerPolynomialsWithDegree<
191    J: Iterator<Item = Integer>,
192    K: Iterator<Item = Integer>,
193>(RandomFixedLengthVecsWithLast<Integer, J, K>);
194
195impl<J: Iterator<Item = Integer>, K: Iterator<Item = Integer>> Iterator
196    for RandomIntegerPolynomialsWithDegree<J, K>
197{
198    type Item = IntegerPolynomial;
199
200    #[inline]
201    fn next(&mut self) -> Option<IntegerPolynomial> {
202        self.0.next().map(IntegerPolynomial::from_coefficients_asc)
203    }
204}
205
206/// The coefficients that the unstriped [`IntegerPolynomial`] generators draw on.
207pub type RandomPolynomialCoefficients = RandomIntegers<GeometricRandomSigneds<i64>>;
208
209/// The leading coefficients that the unstriped [`IntegerPolynomial`] generators draw on: a
210/// polynomial's leading coefficient is never zero.
211pub type RandomPolynomialLeadingCoefficients = RandomIntegers<GeometricRandomNonzeroSigneds<i64>>;
212
213/// The coefficients that the striped [`IntegerPolynomial`] generators draw on.
214pub type StripedRandomPolynomialCoefficients = StripedRandomIntegers<GeometricRandomSigneds<i64>>;
215
216/// The leading coefficients that the striped [`IntegerPolynomial`] generators draw on.
217pub type StripedRandomPolynomialLeadingCoefficients =
218    StripedRandomIntegers<GeometricRandomNonzeroSigneds<i64>>;
219
220/// The type of the [`IntegerPolynomial`] generators whose degrees are uniform over a range.
221pub type RandomIntegerPolynomialsInDegreeRange = RandomIntegerPolynomials<
222    RandomUnsignedInclusiveRange<u64>,
223    RandomPolynomialCoefficients,
224    RandomPolynomialLeadingCoefficients,
225>;
226
227/// The type of the striped [`IntegerPolynomial`] generators with geometrically distributed lengths.
228pub type StripedRandomIntegerPolynomialsFromIntegers = RandomIntegerPolynomials<
229    GeometricRandomNaturalValues<u64>,
230    StripedRandomPolynomialCoefficients,
231    StripedRandomPolynomialLeadingCoefficients,
232>;
233
234/// The type of the striped [`IntegerPolynomial`] generators whose degrees are uniform over a range.
235pub type StripedRandomIntegerPolynomialsInDegreeRange = RandomIntegerPolynomials<
236    RandomUnsignedInclusiveRange<u64>,
237    StripedRandomPolynomialCoefficients,
238    StripedRandomPolynomialLeadingCoefficients,
239>;
240
241/// Generates random [`IntegerPolynomial`]s of a given degree.
242///
243/// A polynomial of degree $d$ has $d+1$ coefficients, of which the leading one is nonzero. The zero
244/// polynomial is never generated: it has no degree at all, so no degree is the one it has.
245///
246/// The coefficients are sampled from [`random_integers`] and the leading coefficient from
247/// [`random_nonzero_integers`], both with a mean bit count of `mean_bits_numerator /
248/// mean_bits_denominator`.
249///
250/// # Worst-case complexity per iteration
251/// $T(i) = O(db)$
252///
253/// $M(i) = O(db)$
254///
255/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $d$ is `degree`, and
256/// $b$ is `mean_bits_numerator / mean_bits_denominator`.
257///
258/// # Panics
259/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if their ratio is less
260/// than or equal to 1.
261///
262/// # Examples
263/// ```
264/// use malachite_base::iterators::prefix_to_string;
265/// use malachite_base::random::EXAMPLE_SEED;
266/// use malachite_nz::integer_polynomial::random::random_integer_polynomials_with_degree;
267///
268/// assert_eq!(
269///     prefix_to_string(
270///         random_integer_polynomials_with_degree(EXAMPLE_SEED, 2, 4, 1),
271///         5
272///     ),
273///     "[14*x^2-x-497, -2*x^2+19*x+1, 2*x^2+799*x+799, 122*x^2+66*x-1, x^2+334*x-10721, ...]"
274/// );
275/// ```
276#[inline]
277pub fn random_integer_polynomials_with_degree(
278    seed: Seed,
279    degree: u64,
280    mean_bits_numerator: u64,
281    mean_bits_denominator: u64,
282) -> RandomIntegerPolynomialsWithDegree<
283    RandomPolynomialCoefficients,
284    RandomPolynomialLeadingCoefficients,
285> {
286    RandomIntegerPolynomialsWithDegree(random_vecs_with_last_fixed_length(
287        degree.saturating_add(1),
288        random_integers(seed.fork("xs"), mean_bits_numerator, mean_bits_denominator),
289        random_nonzero_integers(seed.fork("ys"), mean_bits_numerator, mean_bits_denominator),
290    ))
291}
292
293/// Generates random [`IntegerPolynomial`]s with a minimum degree.
294///
295/// The zero polynomial is never generated: it has no degree at all, so it is not of any degree at
296/// least `min_degree`.
297///
298/// The coefficients are sampled from [`random_integers`] and the leading coefficient from
299/// [`random_nonzero_integers`], both with a mean bit count of `mean_bits_numerator /
300/// mean_bits_denominator`. The lengths — the number of coefficients, which is one more than the
301/// degree — are sampled from a geometric distribution with mean `mean_length_numerator /
302/// mean_length_denominator`, which must be greater than `min_degree + 1`.
303///
304/// # Worst-case complexity per iteration
305/// $T(i) = O(\ell b)$
306///
307/// $M(i) = O(\ell b)$
308///
309/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $\ell$ is the number
310/// of coefficients of the $i$th output, and $b$ is `mean_bits_numerator / mean_bits_denominator`.
311///
312/// # Panics
313/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their ratio is less than
314/// or equal to 1, or if `mean_length_numerator / mean_length_denominator` is less than or equal to
315/// `min_degree + 1`.
316///
317/// # Examples
318/// ```
319/// use malachite_base::iterators::prefix_to_string;
320/// use malachite_base::random::EXAMPLE_SEED;
321/// use malachite_nz::integer_polynomial::random::random_integer_polynomials_min_degree;
322///
323/// assert_eq!(
324///     prefix_to_string(
325///         random_integer_polynomials_min_degree(EXAMPLE_SEED, 1, 4, 1, 3, 1),
326///         5
327///     ),
328///     "[14*x^2-x-497, -2*x^3+799*x^2+19*x+1, 2*x^3+66*x^2-x+799, 122*x^3+59*x^2+334*x-10721, \
329///      x^2-5*x-119, ...]"
330/// );
331/// ```
332#[inline]
333pub fn random_integer_polynomials_min_degree(
334    seed: Seed,
335    min_degree: u64,
336    mean_bits_numerator: u64,
337    mean_bits_denominator: u64,
338    mean_length_numerator: u64,
339    mean_length_denominator: u64,
340) -> RandomIntegerPolynomialsFromIntegers {
341    RandomIntegerPolynomials(random_vecs_with_last_min_length(
342        seed,
343        min_degree.saturating_add(1),
344        &|seed_2| random_integers(seed_2, mean_bits_numerator, mean_bits_denominator),
345        &|seed_2| random_nonzero_integers(seed_2, mean_bits_numerator, mean_bits_denominator),
346        mean_length_numerator,
347        mean_length_denominator,
348    ))
349}
350
351/// Generates random [`IntegerPolynomial`]s with degrees in $[a, b)$.
352///
353/// The degrees are sampled from a uniform distribution on $[a, b)$. The zero polynomial is never
354/// generated: it has no degree at all, so its degree is in no range.
355///
356/// The coefficients are sampled from [`random_integers`] and the leading coefficient from
357/// [`random_nonzero_integers`], both with a mean bit count of `mean_bits_numerator /
358/// mean_bits_denominator`.
359///
360/// # Worst-case complexity per iteration
361/// $T(i) = O(bd)$
362///
363/// $M(i) = O(bd)$
364///
365/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $d$ is $b$, and $b$ is
366/// `mean_bits_numerator / mean_bits_denominator`.
367///
368/// # Panics
369/// Panics if $a \geq b$, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if their
370/// ratio is less than or equal to 1.
371///
372/// # Examples
373/// ```
374/// use malachite_base::iterators::prefix_to_string;
375/// use malachite_base::random::EXAMPLE_SEED;
376/// use malachite_nz::integer_polynomial::random::random_integer_polynomials_degree_range;
377///
378/// assert_eq!(
379///     prefix_to_string(
380///         random_integer_polynomials_degree_range(EXAMPLE_SEED, 1, 3, 4, 1),
381///         5
382///     ),
383///     "[14*x^2-x-497, -2*x+1, 2*x^2+799*x+19, 122*x^2-x+799, x+66, ...]"
384/// );
385/// ```
386#[inline]
387pub fn random_integer_polynomials_degree_range(
388    seed: Seed,
389    a: u64,
390    b: u64,
391    mean_bits_numerator: u64,
392    mean_bits_denominator: u64,
393) -> RandomIntegerPolynomialsInDegreeRange {
394    assert!(a < b, "the degree range [{a}, {b}) is empty");
395    random_integer_polynomials_degree_inclusive_range(
396        seed,
397        a,
398        b - 1,
399        mean_bits_numerator,
400        mean_bits_denominator,
401    )
402}
403
404/// Generates random [`IntegerPolynomial`]s with degrees in $[a, b]$.
405///
406/// The degrees are sampled from a uniform distribution on $[a, b]$. The zero polynomial is never
407/// generated: it has no degree at all, so its degree is in no range.
408///
409/// The coefficients are sampled from [`random_integers`] and the leading coefficient from
410/// [`random_nonzero_integers`], both with a mean bit count of `mean_bits_numerator /
411/// mean_bits_denominator`.
412///
413/// # Worst-case complexity per iteration
414/// $T(i) = O(b^\prime b)$
415///
416/// $M(i) = O(b^\prime b)$
417///
418/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $b^\prime$ is the
419/// largest degree, and $b$ is `mean_bits_numerator / mean_bits_denominator`.
420///
421/// # Panics
422/// Panics if $a > b$, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if their
423/// ratio is less than or equal to 1.
424///
425/// # Examples
426/// ```
427/// use malachite_base::iterators::prefix_to_string;
428/// use malachite_base::random::EXAMPLE_SEED;
429/// use malachite_nz::integer_polynomial::random::*;
430///
431/// assert_eq!(
432///     prefix_to_string(
433///         random_integer_polynomials_degree_inclusive_range(EXAMPLE_SEED, 1, 2, 4, 1),
434///         5
435///     ),
436///     "[14*x^2-x-497, -2*x+1, 2*x^2+799*x+19, 122*x^2-x+799, x+66, ...]"
437/// );
438/// ```
439#[inline]
440pub fn random_integer_polynomials_degree_inclusive_range(
441    seed: Seed,
442    a: u64,
443    b: u64,
444    mean_bits_numerator: u64,
445    mean_bits_denominator: u64,
446) -> RandomIntegerPolynomialsInDegreeRange {
447    assert!(a <= b, "the degree range [{a}, {b}] is empty");
448    RandomIntegerPolynomials(random_vecs_with_last_length_inclusive_range(
449        seed,
450        a.saturating_add(1),
451        b.saturating_add(1),
452        &|seed_2| random_integers(seed_2, mean_bits_numerator, mean_bits_denominator),
453        &|seed_2| random_nonzero_integers(seed_2, mean_bits_numerator, mean_bits_denominator),
454    ))
455}
456
457/// Generates random [`IntegerPolynomial`]s with striped coefficients.
458///
459/// The coefficients are sampled from [`striped_random_integers`] and the leading coefficient from
460/// [`striped_random_nonzero_integers`], with a mean run length of `mean_stripe_numerator /
461/// mean_stripe_denominator` and a mean bit count of `mean_bits_numerator / mean_bits_denominator`.
462/// A striped coefficient is one whose bits come in long runs, which is what makes the carries and
463/// borrows of an arithmetic test interesting.
464///
465/// The lengths — the number of coefficients, which is one more than the degree, or zero for the
466/// zero polynomial — are sampled from a geometric distribution with mean `mean_length_numerator /
467/// mean_length_denominator`, so the zero polynomial is generated with the probability that that
468/// distribution gives to 0.
469///
470/// # Worst-case complexity per iteration
471/// $T(i) = O(\ell b)$
472///
473/// $M(i) = O(\ell b)$
474///
475/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $\ell$ is the number
476/// of coefficients of the $i$th output, and $b$ is `mean_bits_numerator / mean_bits_denominator`.
477///
478/// # Panics
479/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
480/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their
481/// ratio is less than or equal to 1, or if `mean_length_numerator` or `mean_length_denominator` are
482/// zero or their ratio is greater than or equal to $2^{64}$.
483///
484/// # Examples
485/// ```
486/// use malachite_base::iterators::prefix_to_string;
487/// use malachite_base::random::EXAMPLE_SEED;
488/// use malachite_nz::integer_polynomial::random::striped_random_integer_polynomials;
489///
490/// assert_eq!(
491///     prefix_to_string(
492///         striped_random_integer_polynomials(EXAMPLE_SEED, 16, 1, 4, 1, 1, 1),
493///         5
494///     ),
495///     "[15, -2*x-496, 2*x-1, 65*x+1, 1, ...]"
496/// );
497/// ```
498#[inline]
499pub fn striped_random_integer_polynomials(
500    seed: Seed,
501    mean_stripe_numerator: u64,
502    mean_stripe_denominator: u64,
503    mean_bits_numerator: u64,
504    mean_bits_denominator: u64,
505    mean_length_numerator: u64,
506    mean_length_denominator: u64,
507) -> StripedRandomIntegerPolynomialsFromIntegers {
508    random_integer_polynomials_from_iterators(
509        seed,
510        &|seed_2| {
511            striped_random_integers(
512                seed_2,
513                mean_stripe_numerator,
514                mean_stripe_denominator,
515                mean_bits_numerator,
516                mean_bits_denominator,
517            )
518        },
519        &|seed_2| {
520            striped_random_nonzero_integers(
521                seed_2,
522                mean_stripe_numerator,
523                mean_stripe_denominator,
524                mean_bits_numerator,
525                mean_bits_denominator,
526            )
527        },
528        mean_length_numerator,
529        mean_length_denominator,
530    )
531}
532
533/// Generates random [`IntegerPolynomial`]s of a given degree, with striped coefficients.
534///
535/// A polynomial of degree $d$ has $d+1$ coefficients, of which the leading one is nonzero. The zero
536/// polynomial is never generated: it has no degree at all, so no degree is the one it has.
537///
538/// The coefficients are striped, as they are in [`striped_random_integer_polynomials`].
539///
540/// # Worst-case complexity per iteration
541/// $T(i) = O(db)$
542///
543/// $M(i) = O(db)$
544///
545/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $d$ is `degree`, and
546/// $b$ is `mean_bits_numerator / mean_bits_denominator`.
547///
548/// # Panics
549/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
550/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if
551/// their ratio is less than or equal to 1.
552///
553/// # Examples
554/// ```
555/// use malachite_base::iterators::prefix_to_string;
556/// use malachite_base::random::EXAMPLE_SEED;
557/// use malachite_nz::integer_polynomial::random::*;
558///
559/// assert_eq!(
560///     prefix_to_string(
561///         striped_random_integer_polynomials_with_degree(EXAMPLE_SEED, 2, 16, 1, 4, 1),
562///         5
563///     ),
564///     "[15*x^2-x-496, -2*x^2+16*x+1, 2*x^2+543*x+512, 65*x^2+127*x-1, x^2+383*x-10239, ...]"
565/// );
566/// ```
567#[inline]
568pub fn striped_random_integer_polynomials_with_degree(
569    seed: Seed,
570    degree: u64,
571    mean_stripe_numerator: u64,
572    mean_stripe_denominator: u64,
573    mean_bits_numerator: u64,
574    mean_bits_denominator: u64,
575) -> RandomIntegerPolynomialsWithDegree<
576    StripedRandomPolynomialCoefficients,
577    StripedRandomPolynomialLeadingCoefficients,
578> {
579    RandomIntegerPolynomialsWithDegree(random_vecs_with_last_fixed_length(
580        degree.saturating_add(1),
581        striped_random_integers(
582            seed.fork("xs"),
583            mean_stripe_numerator,
584            mean_stripe_denominator,
585            mean_bits_numerator,
586            mean_bits_denominator,
587        ),
588        striped_random_nonzero_integers(
589            seed.fork("ys"),
590            mean_stripe_numerator,
591            mean_stripe_denominator,
592            mean_bits_numerator,
593            mean_bits_denominator,
594        ),
595    ))
596}
597
598/// Generates random [`IntegerPolynomial`]s with a minimum degree and striped coefficients.
599///
600/// The zero polynomial is never generated: it has no degree at all, so it is not of any degree at
601/// least `min_degree`.
602///
603/// The coefficients are striped, as they are in [`striped_random_integer_polynomials`]. The lengths
604/// — one more than the degree — are sampled from a geometric distribution with mean
605/// `mean_length_numerator / mean_length_denominator`, which must be greater than `min_degree + 1`.
606///
607/// # Worst-case complexity per iteration
608/// $T(i) = O(\ell b)$
609///
610/// $M(i) = O(\ell b)$
611///
612/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $\ell$ is the number
613/// of coefficients of the $i$th output, and $b$ is `mean_bits_numerator / mean_bits_denominator`.
614///
615/// # Panics
616/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
617/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their
618/// ratio is less than or equal to 1, or if `mean_length_numerator / mean_length_denominator` is
619/// less than or equal to `min_degree + 1`.
620///
621/// # Examples
622/// ```
623/// use malachite_base::iterators::prefix_to_string;
624/// use malachite_base::random::EXAMPLE_SEED;
625/// use malachite_nz::integer_polynomial::random::*;
626///
627/// assert_eq!(
628///     prefix_to_string(
629///         striped_random_integer_polynomials_min_degree(EXAMPLE_SEED, 1, 16, 1, 4, 1, 3, 1),
630///         5
631///     ),
632///     "[15*x^2-x-496, -2*x^3+512*x^2+16*x+1, 2*x^3+127*x^2-x+543, 65*x^3+36*x^2+383*x-10239, \
633///      x^2-4*x-127, ...]"
634/// );
635/// ```
636#[inline]
637pub fn striped_random_integer_polynomials_min_degree(
638    seed: Seed,
639    min_degree: u64,
640    mean_stripe_numerator: u64,
641    mean_stripe_denominator: u64,
642    mean_bits_numerator: u64,
643    mean_bits_denominator: u64,
644    mean_length_numerator: u64,
645    mean_length_denominator: u64,
646) -> StripedRandomIntegerPolynomialsFromIntegers {
647    RandomIntegerPolynomials(random_vecs_with_last_min_length(
648        seed,
649        min_degree.saturating_add(1),
650        &|seed_2| {
651            striped_random_integers(
652                seed_2,
653                mean_stripe_numerator,
654                mean_stripe_denominator,
655                mean_bits_numerator,
656                mean_bits_denominator,
657            )
658        },
659        &|seed_2| {
660            striped_random_nonzero_integers(
661                seed_2,
662                mean_stripe_numerator,
663                mean_stripe_denominator,
664                mean_bits_numerator,
665                mean_bits_denominator,
666            )
667        },
668        mean_length_numerator,
669        mean_length_denominator,
670    ))
671}
672
673/// Generates random [`IntegerPolynomial`]s with degrees in $[a, b)$ and striped coefficients.
674///
675/// The degrees are sampled from a uniform distribution on $[a, b)$. The zero polynomial is never
676/// generated: it has no degree at all, so its degree is in no range.
677///
678/// The coefficients are striped, as they are in [`striped_random_integer_polynomials`].
679///
680/// # Worst-case complexity per iteration
681/// $T(i) = O(bd)$
682///
683/// $M(i) = O(bd)$
684///
685/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $d$ is $b$, and $b$ is
686/// `mean_bits_numerator / mean_bits_denominator`.
687///
688/// # Panics
689/// Panics if $a \geq b$, if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
690/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if
691/// their ratio is less than or equal to 1.
692///
693/// # Examples
694/// ```
695/// use malachite_base::iterators::prefix_to_string;
696/// use malachite_base::random::EXAMPLE_SEED;
697/// use malachite_nz::integer_polynomial::random::*;
698///
699/// assert_eq!(
700///     prefix_to_string(
701///         striped_random_integer_polynomials_degree_range(EXAMPLE_SEED, 1, 3, 16, 1, 4, 1),
702///         5
703///     ),
704///     "[15*x^2-x-496, -2*x+1, 2*x^2+512*x+16, 65*x^2-x+543, x+127, ...]"
705/// );
706/// ```
707#[inline]
708pub fn striped_random_integer_polynomials_degree_range(
709    seed: Seed,
710    a: u64,
711    b: u64,
712    mean_stripe_numerator: u64,
713    mean_stripe_denominator: u64,
714    mean_bits_numerator: u64,
715    mean_bits_denominator: u64,
716) -> StripedRandomIntegerPolynomialsInDegreeRange {
717    assert!(a < b, "the degree range [{a}, {b}) is empty");
718    striped_random_integer_polynomials_degree_inclusive_range(
719        seed,
720        a,
721        b - 1,
722        mean_stripe_numerator,
723        mean_stripe_denominator,
724        mean_bits_numerator,
725        mean_bits_denominator,
726    )
727}
728
729/// Generates random [`IntegerPolynomial`]s with degrees in $[a, b]$ and striped coefficients.
730///
731/// The degrees are sampled from a uniform distribution on $[a, b]$. The zero polynomial is never
732/// generated: it has no degree at all, so its degree is in no range.
733///
734/// The coefficients are striped, as they are in [`striped_random_integer_polynomials`].
735///
736/// # Worst-case complexity per iteration
737/// $T(i) = O(b^\prime b)$
738///
739/// $M(i) = O(b^\prime b)$
740///
741/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $b^\prime$ is the
742/// largest degree, and $b$ is `mean_bits_numerator / mean_bits_denominator`.
743///
744/// # Panics
745/// Panics if $a > b$, if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
746/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if
747/// their ratio is less than or equal to 1.
748///
749/// # Examples
750/// ```
751/// use malachite_base::iterators::prefix_to_string;
752/// use malachite_base::random::EXAMPLE_SEED;
753/// use malachite_nz::integer_polynomial::random::*;
754///
755/// assert_eq!(
756///     prefix_to_string(
757///         striped_random_integer_polynomials_degree_inclusive_range(
758///             EXAMPLE_SEED,
759///             1,
760///             2,
761///             16,
762///             1,
763///             4,
764///             1
765///         ),
766///         5
767///     ),
768///     "[15*x^2-x-496, -2*x+1, 2*x^2+512*x+16, 65*x^2-x+543, x+127, ...]"
769/// );
770/// ```
771#[inline]
772pub fn striped_random_integer_polynomials_degree_inclusive_range(
773    seed: Seed,
774    a: u64,
775    b: u64,
776    mean_stripe_numerator: u64,
777    mean_stripe_denominator: u64,
778    mean_bits_numerator: u64,
779    mean_bits_denominator: u64,
780) -> StripedRandomIntegerPolynomialsInDegreeRange {
781    assert!(a <= b, "the degree range [{a}, {b}] is empty");
782    RandomIntegerPolynomials(random_vecs_with_last_length_inclusive_range(
783        seed,
784        a.saturating_add(1),
785        b.saturating_add(1),
786        &|seed_2| {
787            striped_random_integers(
788                seed_2,
789                mean_stripe_numerator,
790                mean_stripe_denominator,
791                mean_bits_numerator,
792                mean_bits_denominator,
793            )
794        },
795        &|seed_2| {
796            striped_random_nonzero_integers(
797                seed_2,
798                mean_stripe_numerator,
799                mean_stripe_denominator,
800                mean_bits_numerator,
801                mean_bits_denominator,
802            )
803        },
804    ))
805}