malachite_base/tuples/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
9/// Generates all singletons (1-element tuples) with values from a given iterator.
10///
11/// This `struct` is created by [`singletons`]; see its documentation for more.
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub struct Singletons<I: Iterator> {
14 xs: I,
15}
16
17impl<I: Iterator> Iterator for Singletons<I> {
18 type Item = (I::Item,);
19
20 #[inline]
21 fn next(&mut self) -> Option<(I::Item,)> {
22 self.xs.next().map(|x| (x,))
23 }
24}
25
26/// Generates all singletons (1-element tuples) with values from a given iterator.
27///
28/// The elements appear in the same order as they do in the given iterator, but wrapped in `(_,)`.
29///
30/// The output length is `xs.count()`.
31///
32/// # Worst-case complexity per iteration
33/// $T(i) = O(T^\prime(i))$
34///
35/// $M(i) = O(M^\prime(i))$
36///
37/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, and $T^\prime$ and
38/// $M^\prime$ are the time and memory functions of `xs`.
39///
40/// # Examples
41/// ```
42/// use itertools::Itertools;
43/// use malachite_base::tuples::singletons;
44///
45/// assert_eq!(
46/// singletons([1, 2, 3].iter().cloned()).collect_vec(),
47/// &[(1,), (2,), (3,)]
48/// );
49/// ```
50#[inline]
51pub const fn singletons<I: Iterator>(xs: I) -> Singletons<I> {
52 Singletons { xs }
53}
54
55/// Iterators that generate tuples without repetition.
56///
57/// To reduce binary size and lower compilation time, many of the functions described here are not
58/// actually defined in Malachite, but may be created in your program using macros exported from
59/// Malachite. To do this, see the documentation for `lex_tuples` and `lex_custom_tuples`.
60///
61/// # lex_pairs
62/// ```
63/// use itertools::Itertools;
64/// use malachite_base::tuples::exhaustive::lex_pairs;
65///
66/// assert_eq!(
67/// lex_pairs('a'..'f', 0..3).collect_vec(),
68/// &[
69/// ('a', 0),
70/// ('a', 1),
71/// ('a', 2),
72/// ('b', 0),
73/// ('b', 1),
74/// ('b', 2),
75/// ('c', 0),
76/// ('c', 1),
77/// ('c', 2),
78/// ('d', 0),
79/// ('d', 1),
80/// ('d', 2),
81/// ('e', 0),
82/// ('e', 1),
83/// ('e', 2)
84/// ]
85/// );
86/// ```
87///
88/// # lex_pairs_from_single
89/// ```
90/// use itertools::Itertools;
91/// use malachite_base::tuples::exhaustive::lex_pairs_from_single;
92///
93/// assert_eq!(
94/// lex_pairs_from_single(0..3).collect_vec(),
95/// &[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
96/// );
97/// ```
98///
99/// # lex_triples_xyx
100/// ```
101/// use itertools::Itertools;
102/// use malachite_base::iterators::iterator_cache::IteratorCache;
103/// use malachite_base::lex_custom_tuples;
104///
105/// fn unwrap_triple<X, Y, Z>((a, b, c): (Option<X>, Option<Y>, Option<Z>)) -> (X, Y, Z) {
106/// (a.unwrap(), b.unwrap(), c.unwrap())
107/// }
108///
109/// lex_custom_tuples!(
110/// (pub(crate)),
111/// LexTriplesXYX,
112/// (X, Y, X),
113/// (None, None, None),
114/// unwrap_triple,
115/// lex_triples_xyx,
116/// [X, I, xs, [0, x_0], [2, x_2]],
117/// [Y, J, ys, [1, y_1]]
118/// );
119///
120/// // We are generating triples of `char`, `i8`, and `char` using two input iterators. The first
121/// // iterator, `xs`, the chars 'a' through 'c', and the second, `ys`, produces the three numbers
122/// // 0, 1, and 2. The function we're using is `lex_triples_xyx`, meaning that the first element of
123/// // the output triples will be taken from `xs`, the second element from `ys`, and the third also
124/// // from `xs`.
125/// let ts = lex_triples_xyx('a'..='c', 0..3);
126/// assert_eq!(
127/// ts.collect_vec(),
128/// &[
129/// ('a', 0, 'a'),
130/// ('a', 0, 'b'),
131/// ('a', 0, 'c'),
132/// ('a', 1, 'a'),
133/// ('a', 1, 'b'),
134/// ('a', 1, 'c'),
135/// ('a', 2, 'a'),
136/// ('a', 2, 'b'),
137/// ('a', 2, 'c'),
138/// ('b', 0, 'a'),
139/// ('b', 0, 'b'),
140/// ('b', 0, 'c'),
141/// ('b', 1, 'a'),
142/// ('b', 1, 'b'),
143/// ('b', 1, 'c'),
144/// ('b', 2, 'a'),
145/// ('b', 2, 'b'),
146/// ('b', 2, 'c'),
147/// ('c', 0, 'a'),
148/// ('c', 0, 'b'),
149/// ('c', 0, 'c'),
150/// ('c', 1, 'a'),
151/// ('c', 1, 'b'),
152/// ('c', 1, 'c'),
153/// ('c', 2, 'a'),
154/// ('c', 2, 'b'),
155/// ('c', 2, 'c')
156/// ]
157/// );
158/// ```
159///
160/// # exhaustive_pairs_from_single
161/// ```
162/// use itertools::Itertools;
163/// use malachite_base::tuples::exhaustive::exhaustive_pairs_from_single;
164///
165/// assert_eq!(
166/// exhaustive_pairs_from_single(0..4).collect_vec(),
167/// &[
168/// (0, 0),
169/// (0, 1),
170/// (1, 0),
171/// (1, 1),
172/// (0, 2),
173/// (0, 3),
174/// (1, 2),
175/// (1, 3),
176/// (2, 0),
177/// (2, 1),
178/// (3, 0),
179/// (3, 1),
180/// (2, 2),
181/// (2, 3),
182/// (3, 2),
183/// (3, 3)
184/// ]
185/// );
186/// ```
187///
188/// # exhaustive_pairs_1_input
189/// ```
190/// use itertools::Itertools;
191/// use malachite_base::chars::exhaustive::exhaustive_ascii_chars;
192/// use malachite_base::exhaustive_tuples_1_input;
193/// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType};
194/// use malachite_base::iterators::iterator_cache::IteratorCache;
195/// use malachite_base::num::arithmetic::traits::CheckedPow;
196/// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
197/// use malachite_base::num::logic::traits::SignificantBits;
198/// use std::cmp::max;
199/// use std::marker::PhantomData;
200///
201/// exhaustive_tuples_1_input!(
202/// (pub(crate)),
203/// ExhaustiveTriples1Input,
204/// exhaustive_triples_1_input,
205/// exhaustive_triples_from_single,
206/// (I::Item, I::Item, I::Item),
207/// [0, output_type_x],
208/// [1, output_type_y],
209/// [2, output_type_z]
210/// );
211///
212/// // We are generating triples of `char`s using one input iterator, which produces all ASCII
213/// // `char`s. The third element has a tiny output type, so it will grow more slowly than the other
214/// // two elements (though it doesn't look that way from the first few tuples).
215/// let ts = exhaustive_triples_1_input(
216/// exhaustive_ascii_chars(),
217/// BitDistributorOutputType::normal(1),
218/// BitDistributorOutputType::normal(1),
219/// BitDistributorOutputType::tiny(),
220/// );
221/// assert_eq!(
222/// ts.take(20).collect_vec(),
223/// &[
224/// ('a', 'a', 'a'),
225/// ('a', 'a', 'b'),
226/// ('a', 'a', 'c'),
227/// ('a', 'a', 'd'),
228/// ('a', 'b', 'a'),
229/// ('a', 'b', 'b'),
230/// ('a', 'b', 'c'),
231/// ('a', 'b', 'd'),
232/// ('a', 'a', 'e'),
233/// ('a', 'a', 'f'),
234/// ('a', 'a', 'g'),
235/// ('a', 'a', 'h'),
236/// ('a', 'b', 'e'),
237/// ('a', 'b', 'f'),
238/// ('a', 'b', 'g'),
239/// ('a', 'b', 'h'),
240/// ('b', 'a', 'a'),
241/// ('b', 'a', 'b'),
242/// ('b', 'a', 'c'),
243/// ('b', 'a', 'd')
244/// ]
245/// );
246/// ```
247///
248/// # exhaustive_pairs
249/// ```
250/// use itertools::Itertools;
251/// use malachite_base::tuples::exhaustive::exhaustive_pairs;
252///
253/// let xss = exhaustive_pairs(['a', 'b', 'c'].iter().cloned(), 0..3).collect_vec();
254/// assert_eq!(
255/// xss,
256/// &[('a', 0), ('a', 1), ('b', 0), ('b', 1), ('a', 2), ('b', 2), ('c', 0), ('c', 1), ('c', 2)]
257/// );
258/// ```
259///
260/// # exhaustive_pairs_custom_output
261/// ```
262/// use itertools::Itertools;
263/// use malachite_base::iterators::bit_distributor::BitDistributorOutputType;
264/// use malachite_base::tuples::exhaustive::exhaustive_pairs_custom_output;
265///
266/// let xss = exhaustive_pairs_custom_output(
267/// ['a', 'b', 'c'].iter().cloned(),
268/// 0..3,
269/// BitDistributorOutputType::normal(1),
270/// BitDistributorOutputType::tiny(),
271/// )
272/// .collect_vec();
273/// assert_eq!(
274/// xss,
275/// &[('a', 0), ('a', 1), ('a', 2), ('b', 0), ('b', 1), ('b', 2), ('c', 0), ('c', 1), ('c', 2)]
276/// );
277/// ```
278///
279/// # exhaustive_triples_xyx
280/// ```
281/// use itertools::Itertools;
282/// use malachite_base::chars::exhaustive::exhaustive_ascii_chars;
283/// use malachite_base::custom_tuples;
284/// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType};
285/// use malachite_base::iterators::iterator_cache::IteratorCache;
286/// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
287/// use malachite_base::num::logic::traits::SignificantBits;
288/// use std::cmp::max;
289///
290/// #[allow(clippy::missing_const_for_fn)]
291/// fn unwrap_triple<X, Y, Z>((a, b, c): (Option<X>, Option<Y>, Option<Z>)) -> (X, Y, Z) {
292/// (a.unwrap(), b.unwrap(), c.unwrap())
293/// }
294///
295/// custom_tuples!(
296/// (pub(crate)),
297/// ExhaustiveTriplesXYX,
298/// (X, Y, X),
299/// (None, None, None),
300/// unwrap_triple,
301/// exhaustive_triples_xyx,
302/// exhaustive_triples_xyx_custom_output,
303/// [X, I, xs, xs_done, [0, output_type_xs_0], [2, output_type_ys_1]],
304/// [Y, J, ys, ys_done, [1, output_type_xs_2]]
305/// );
306///
307/// // We are generating triples of `char`, `i8`, and `char` using two input iterators. The first
308/// // iterator, `xs`, produces all ASCII `char`s, and the second, `ys`, produces the three numbers
309/// // 0, 1, and 2. The function we're using is `exhaustive_triples_xyx`, meaning that the first
310/// // element of the output triples will be taken from `xs`, the second element from `ys`, and the
311/// // third also from `xs`.
312/// let ts = exhaustive_triples_xyx(exhaustive_ascii_chars(), 0..3);
313/// assert_eq!(
314/// ts.take(20).collect_vec(),
315/// &[
316/// ('a', 0, 'a'),
317/// ('a', 0, 'b'),
318/// ('a', 1, 'a'),
319/// ('a', 1, 'b'),
320/// ('b', 0, 'a'),
321/// ('b', 0, 'b'),
322/// ('b', 1, 'a'),
323/// ('b', 1, 'b'),
324/// ('a', 0, 'c'),
325/// ('a', 0, 'd'),
326/// ('a', 1, 'c'),
327/// ('a', 1, 'd'),
328/// ('b', 0, 'c'),
329/// ('b', 0, 'd'),
330/// ('b', 1, 'c'),
331/// ('b', 1, 'd'),
332/// ('a', 2, 'a'),
333/// ('a', 2, 'b'),
334/// ('b', 2, 'a'),
335/// ('b', 2, 'b')
336/// ]
337/// );
338/// ```
339///
340/// # exhaustive_triples_xyx_custom_output
341/// ```
342/// use itertools::Itertools;
343/// use malachite_base::chars::exhaustive::exhaustive_ascii_chars;
344/// use malachite_base::custom_tuples;
345/// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType};
346/// use malachite_base::iterators::iterator_cache::IteratorCache;
347/// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
348/// use malachite_base::num::logic::traits::SignificantBits;
349/// use std::cmp::max;
350///
351/// #[allow(clippy::missing_const_for_fn)]
352/// fn unwrap_triple<X, Y, Z>((a, b, c): (Option<X>, Option<Y>, Option<Z>)) -> (X, Y, Z) {
353/// (a.unwrap(), b.unwrap(), c.unwrap())
354/// }
355///
356/// custom_tuples!(
357/// (pub(crate)),
358/// ExhaustiveTriplesXYX,
359/// (X, Y, X),
360/// (None, None, None),
361/// unwrap_triple,
362/// exhaustive_triples_xyx,
363/// exhaustive_triples_xyx_custom_output,
364/// [X, I, xs, xs_done, [0, output_type_xs_0], [2, output_type_ys_1]],
365/// [Y, J, ys, ys_done, [1, output_type_xs_2]]
366/// );
367///
368/// // We are generating triples of `char`, `i8`, and `char` using two input iterators. The first
369/// // iterator, `xs`, produces all ASCII `char`s, and the second, `ys`, produces the three numbers
370/// // 0, 1, and 2. The function we're using is `exhaustive_triples_xyx_custom_output`, meaning that
371/// // the first element of the output triples will be taken from `xs`, the second element from
372/// // `ys`, and the third also from `xs`.
373/// //
374/// // The third element has a tiny output type, so it will grow more slowly than the other two
375/// // elements (though it doesn't look that way from the first few tuples).
376/// let ts = exhaustive_triples_xyx_custom_output(
377/// exhaustive_ascii_chars(),
378/// 0..3,
379/// BitDistributorOutputType::normal(1),
380/// BitDistributorOutputType::normal(1),
381/// BitDistributorOutputType::tiny(),
382/// );
383/// assert_eq!(
384/// ts.take(20).collect_vec(),
385/// &[
386/// ('a', 0, 'a'),
387/// ('a', 0, 'b'),
388/// ('a', 0, 'c'),
389/// ('a', 0, 'd'),
390/// ('a', 1, 'a'),
391/// ('a', 1, 'b'),
392/// ('a', 1, 'c'),
393/// ('a', 1, 'd'),
394/// ('a', 0, 'e'),
395/// ('a', 0, 'f'),
396/// ('a', 0, 'g'),
397/// ('a', 0, 'h'),
398/// ('a', 1, 'e'),
399/// ('a', 1, 'f'),
400/// ('a', 1, 'g'),
401/// ('a', 1, 'h'),
402/// ('b', 0, 'a'),
403/// ('b', 0, 'b'),
404/// ('b', 0, 'c'),
405/// ('b', 0, 'd')
406/// ]
407/// );
408/// ```
409///
410/// # lex_ordered_unique_quadruples
411/// ```
412/// use itertools::Itertools;
413/// use malachite_base::iterators::iterator_cache::IteratorCache;
414/// use malachite_base::lex_ordered_unique_tuples;
415/// use malachite_base::vecs::exhaustive::fixed_length_ordered_unique_indices_helper;
416/// use std::marker::PhantomData;
417///
418/// lex_ordered_unique_tuples!(
419/// (pub(crate)),
420/// LexOrderedUniqueQuadruples,
421/// 4,
422/// (I::Item, I::Item, I::Item, I::Item),
423/// lex_ordered_unique_quadruples,
424/// [0, 1, 2, 3]
425/// );
426///
427/// let xss = lex_ordered_unique_quadruples(1..=6).collect_vec();
428/// assert_eq!(
429/// xss.into_iter().collect_vec().as_slice(),
430/// &[
431/// (1, 2, 3, 4),
432/// (1, 2, 3, 5),
433/// (1, 2, 3, 6),
434/// (1, 2, 4, 5),
435/// (1, 2, 4, 6),
436/// (1, 2, 5, 6),
437/// (1, 3, 4, 5),
438/// (1, 3, 4, 6),
439/// (1, 3, 5, 6),
440/// (1, 4, 5, 6),
441/// (2, 3, 4, 5),
442/// (2, 3, 4, 6),
443/// (2, 3, 5, 6),
444/// (2, 4, 5, 6),
445/// (3, 4, 5, 6)
446/// ]
447/// );
448/// ```
449///
450/// # exhaustive_ordered_unique_quadruples
451/// ```
452/// use itertools::Itertools;
453/// use malachite_base::exhaustive_ordered_unique_tuples;
454/// use malachite_base::iterators::iterator_cache::IteratorCache;
455/// use malachite_base::vecs::exhaustive::next_bit_pattern;
456///
457/// exhaustive_ordered_unique_tuples!(
458/// (pub(crate)),
459/// ExhaustiveOrderedUniqueQuadruples,
460/// 4,
461/// (I::Item, I::Item, I::Item, I::Item),
462/// exhaustive_ordered_unique_quadruples,
463/// [0, 1, 2, 3]
464/// );
465///
466/// let xss = exhaustive_ordered_unique_quadruples(1..=6).collect_vec();
467/// assert_eq!(
468/// xss.into_iter().collect_vec().as_slice(),
469/// &[
470/// (1, 2, 3, 4),
471/// (1, 2, 3, 5),
472/// (1, 2, 4, 5),
473/// (1, 3, 4, 5),
474/// (2, 3, 4, 5),
475/// (1, 2, 3, 6),
476/// (1, 2, 4, 6),
477/// (1, 3, 4, 6),
478/// (2, 3, 4, 6),
479/// (1, 2, 5, 6),
480/// (1, 3, 5, 6),
481/// (2, 3, 5, 6),
482/// (1, 4, 5, 6),
483/// (2, 4, 5, 6),
484/// (3, 4, 5, 6)
485/// ]
486/// );
487/// ```
488///
489/// # lex_unique_quadruples
490/// ```
491/// use itertools::Itertools;
492/// use malachite_base::iterators::iterator_cache::IteratorCache;
493/// use malachite_base::lex_unique_tuples;
494/// use malachite_base::vecs::exhaustive::{UniqueIndices, unique_indices};
495///
496/// lex_unique_tuples!(
497/// (pub(crate)),
498/// LexUniqueQuadruples,
499/// 4,
500/// (I::Item, I::Item, I::Item, I::Item),
501/// lex_unique_quadruples,
502/// [0, 1, 2, 3]
503/// );
504///
505/// let xss = lex_unique_quadruples(1..=6).take(20).collect_vec();
506/// assert_eq!(
507/// xss.into_iter().collect_vec().as_slice(),
508/// &[
509/// (1, 2, 3, 4),
510/// (1, 2, 3, 5),
511/// (1, 2, 3, 6),
512/// (1, 2, 4, 3),
513/// (1, 2, 4, 5),
514/// (1, 2, 4, 6),
515/// (1, 2, 5, 3),
516/// (1, 2, 5, 4),
517/// (1, 2, 5, 6),
518/// (1, 2, 6, 3),
519/// (1, 2, 6, 4),
520/// (1, 2, 6, 5),
521/// (1, 3, 2, 4),
522/// (1, 3, 2, 5),
523/// (1, 3, 2, 6),
524/// (1, 3, 4, 2),
525/// (1, 3, 4, 5),
526/// (1, 3, 4, 6),
527/// (1, 3, 5, 2),
528/// (1, 3, 5, 4)
529/// ]
530/// );
531/// ```
532///
533/// # exhaustive_unique_quadruples
534/// ```
535/// use itertools::Itertools;
536/// use malachite_base::exhaustive_unique_tuples;
537/// use malachite_base::num::iterators::{RulerSequence, ruler_sequence};
538/// use malachite_base::tuples::exhaustive::{
539/// ExhaustiveDependentPairs, exhaustive_dependent_pairs,
540/// };
541/// use malachite_base::vecs::ExhaustiveVecPermutations;
542/// use malachite_base::vecs::exhaustive::{
543/// ExhaustiveOrderedUniqueCollections, ExhaustiveUniqueVecsGenerator,
544/// exhaustive_ordered_unique_vecs_fixed_length,
545/// };
546///
547/// exhaustive_unique_tuples!(
548/// (pub(crate)),
549/// ExhaustiveUniqueQuadruples,
550/// 4,
551/// (I::Item, I::Item, I::Item, I::Item),
552/// exhaustive_unique_quadruples,
553/// [0, 1, 2, 3]
554/// );
555///
556/// let xss = exhaustive_unique_quadruples(1..=6).take(20).collect_vec();
557/// assert_eq!(
558/// xss.into_iter().collect_vec().as_slice(),
559/// &[
560/// (1, 2, 3, 4),
561/// (1, 2, 3, 5),
562/// (1, 2, 4, 3),
563/// (1, 2, 4, 5),
564/// (1, 3, 2, 4),
565/// (1, 2, 5, 3),
566/// (1, 3, 4, 2),
567/// (1, 3, 4, 5),
568/// (1, 4, 2, 3),
569/// (1, 3, 2, 5),
570/// (1, 4, 3, 2),
571/// (1, 2, 5, 4),
572/// (2, 1, 3, 4),
573/// (1, 3, 5, 2),
574/// (2, 1, 4, 3),
575/// (2, 3, 4, 5),
576/// (2, 3, 1, 4),
577/// (1, 5, 2, 3),
578/// (2, 3, 4, 1),
579/// (1, 4, 2, 5)
580/// ]
581/// );
582/// ```
583pub mod exhaustive;
584#[cfg(feature = "random")]
585/// Iterators that generate tuples randomly.
586///
587/// # random_pairs
588/// ```
589/// use itertools::Itertools;
590/// use malachite_base::chars::random::random_char_inclusive_range;
591/// use malachite_base::num::random::random_unsigned_inclusive_range;
592/// use malachite_base::random::EXAMPLE_SEED;
593/// use malachite_base::tuples::random::random_pairs;
594///
595/// let ps = random_pairs(
596/// EXAMPLE_SEED,
597/// &|seed| random_unsigned_inclusive_range::<u8>(seed, 0, 2),
598/// &|seed| random_char_inclusive_range(seed, 'x', 'z'),
599/// );
600/// assert_eq!(
601/// ps.take(20).collect_vec().as_slice(),
602/// &[
603/// (1, 'z'),
604/// (1, 'x'),
605/// (1, 'z'),
606/// (1, 'y'),
607/// (2, 'x'),
608/// (0, 'z'),
609/// (0, 'z'),
610/// (0, 'z'),
611/// (2, 'z'),
612/// (0, 'y'),
613/// (2, 'x'),
614/// (0, 'x'),
615/// (2, 'z'),
616/// (0, 'z'),
617/// (2, 'x'),
618/// (2, 'x'),
619/// (2, 'y'),
620/// (1, 'y'),
621/// (0, 'x'),
622/// (2, 'x')
623/// ]
624/// );
625/// ```
626///
627/// # random_pairs_from_single
628/// ```
629/// use itertools::Itertools;
630/// use malachite_base::num::random::random_unsigned_inclusive_range;
631/// use malachite_base::random::EXAMPLE_SEED;
632/// use malachite_base::tuples::random::random_pairs_from_single;
633///
634/// let ps = random_pairs_from_single(random_unsigned_inclusive_range::<u8>(EXAMPLE_SEED, 0, 2));
635/// assert_eq!(
636/// ps.take(20).collect_vec().as_slice(),
637/// &[
638/// (1, 0),
639/// (1, 2),
640/// (1, 1),
641/// (0, 1),
642/// (0, 2),
643/// (1, 0),
644/// (1, 2),
645/// (2, 0),
646/// (1, 0),
647/// (2, 2),
648/// (2, 1),
649/// (0, 2),
650/// (2, 1),
651/// (1, 1),
652/// (0, 0),
653/// (2, 0),
654/// (2, 2),
655/// (1, 0),
656/// (1, 1),
657/// (0, 2)
658/// ]
659/// );
660/// ```
661///
662/// # random_triples_xyx
663/// ```
664/// use itertools::Itertools;
665/// use malachite_base::chars::random::random_char_inclusive_range;
666/// use malachite_base::num::random::random_unsigned_inclusive_range;
667/// use malachite_base::random::{EXAMPLE_SEED, Seed};
668/// use malachite_base::random_custom_tuples;
669///
670/// random_custom_tuples!(
671/// (pub(crate)),
672/// RandomTriplesXYX,
673/// (X, Y, X),
674/// random_triples_xyx,
675/// [X, I, xs, xs_gen, [x_0, x_0], [x_2, y_1]],
676/// [Y, J, ys, ys_gen, [y_1, x_2]]
677/// );
678///
679/// // We are generating triples of `char`s using two input iterators. The first iterator, `xs`,
680/// // produces all ASCII `char`s, and the second, `ys`, produces the three numbers 0, 1, and 2. The
681/// // function we're using is `random_triples_xyx`, meaning that the first element of the
682/// // output triples will be taken from `xs`, the second element from `ys`, and the third also from
683/// // `xs`.
684/// let ts = random_triples_xyx(
685/// EXAMPLE_SEED,
686/// &|seed| random_char_inclusive_range(seed, 'x', 'z'),
687/// &|seed| random_unsigned_inclusive_range::<u8>(seed, 0, 2),
688/// );
689/// assert_eq!(
690/// ts.take(20).collect_vec().as_slice(),
691/// &[
692/// ('y', 2, 'y'),
693/// ('y', 0, 'y'),
694/// ('z', 2, 'x'),
695/// ('x', 1, 'x'),
696/// ('z', 0, 'x'),
697/// ('z', 2, 'x'),
698/// ('z', 2, 'x'),
699/// ('z', 2, 'z'),
700/// ('z', 2, 'y'),
701/// ('x', 1, 'z'),
702/// ('z', 0, 'x'),
703/// ('y', 0, 'z'),
704/// ('y', 2, 'z'),
705/// ('x', 2, 'z'),
706/// ('z', 0, 'y'),
707/// ('z', 0, 'y'),
708/// ('y', 1, 'x'),
709/// ('z', 1, 'z'),
710/// ('x', 0, 'z'),
711/// ('z', 0, 'x')
712/// ]
713/// );
714/// ```
715///
716/// # random_ordered_unique_quadruples
717/// ```
718/// use itertools::Itertools;
719/// use malachite_base::num::random::random_unsigned_inclusive_range;
720/// use malachite_base::random::EXAMPLE_SEED;
721/// use malachite_base::random_ordered_unique_tuples;
722/// use malachite_base::sets::random::{
723/// RandomBTreeSetsFixedLength, random_b_tree_sets_fixed_length,
724/// };
725///
726/// random_ordered_unique_tuples!(
727/// (pub(crate)),
728/// RandomOrderedUniqueQuadruples,
729/// 4,
730/// (I::Item, I::Item, I::Item, I::Item),
731/// random_ordered_unique_quadruples,
732/// [0, 1, 2, 3]
733/// );
734///
735/// let qs = random_ordered_unique_quadruples(random_unsigned_inclusive_range::<u8>(
736/// EXAMPLE_SEED,
737/// 1,
738/// 10,
739/// ));
740/// assert_eq!(
741/// qs.take(20).collect_vec().as_slice(),
742/// &[
743/// (2, 5, 6, 8),
744/// (3, 5, 7, 9),
745/// (1, 2, 6, 8),
746/// (3, 4, 6, 7),
747/// (3, 6, 9, 10),
748/// (4, 6, 8, 10),
749/// (3, 6, 8, 10),
750/// (2, 5, 9, 10),
751/// (2, 3, 8, 10),
752/// (1, 3, 7, 8),
753/// (1, 2, 6, 10),
754/// (2, 5, 8, 9),
755/// (1, 8, 9, 10),
756/// (1, 3, 7, 8),
757/// (2, 3, 4, 5),
758/// (1, 3, 4, 8),
759/// (3, 6, 7, 9),
760/// (5, 6, 7, 8),
761/// (3, 4, 5, 9),
762/// (4, 6, 9, 10)
763/// ]
764/// );
765/// ```
766///
767/// # random_unique_quadruples
768/// ```
769/// use itertools::Itertools;
770/// use malachite_base::num::random::random_unsigned_inclusive_range;
771/// use malachite_base::random::EXAMPLE_SEED;
772/// use malachite_base::random_unique_tuples;
773/// use std::collections::HashMap;
774/// use std::hash::Hash;
775///
776/// random_unique_tuples!(
777/// (pub(crate)),
778/// RandomOrderedUniqueQuadruples,
779/// 4,
780/// (I::Item, I::Item, I::Item, I::Item),
781/// random_unique_quadruples,
782/// [0, 1, 2, 3]
783/// );
784///
785/// let qs = random_unique_quadruples(random_unsigned_inclusive_range::<u8>(EXAMPLE_SEED, 1, 10));
786/// assert_eq!(
787/// qs.take(20).collect_vec().as_slice(),
788/// &[
789/// (2, 8, 6, 5),
790/// (7, 5, 3, 9),
791/// (2, 8, 6, 1),
792/// (3, 7, 4, 6),
793/// (3, 10, 6, 9),
794/// (6, 10, 4, 8),
795/// (6, 10, 8, 3),
796/// (10, 2, 9, 5),
797/// (8, 10, 2, 3),
798/// (8, 1, 7, 3),
799/// (2, 6, 1, 10),
800/// (9, 5, 8, 2),
801/// (8, 1, 9, 10),
802/// (7, 3, 8, 1),
803/// (3, 2, 5, 4),
804/// (3, 8, 4, 1),
805/// (9, 7, 6, 3),
806/// (5, 7, 8, 6),
807/// (5, 3, 9, 4),
808/// (9, 10, 4, 6)
809/// ]
810/// );
811/// ```
812pub mod random;