malachite_base/tuples/random.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::random::Seed;
10use std::cmp::Ordering::*;
11use std::iter::{Repeat, repeat};
12
13/// Generates random units; repeats `()`.
14///
15/// $P(()) = 1$.
16///
17/// The output length is infinite.
18///
19/// # Expected complexity per iteration
20/// Constant time and additional memory.
21///
22/// # Examples
23/// ```
24/// use itertools::Itertools;
25/// use malachite_base::tuples::random::random_units;
26///
27/// assert_eq!(random_units().take(10).collect_vec(), &[(); 10]);
28/// ```
29#[inline]
30pub fn random_units() -> Repeat<()> {
31 repeat(())
32}
33
34// hack for macro
35#[doc(hidden)]
36#[inline]
37pub fn next_helper<I: Iterator>(x: &mut I, _i: usize) -> Option<I::Item> {
38 x.next()
39}
40
41/// Defines random tuple generators.
42///
43/// Malachite provides [`random_pairs`] and [`random_pairs_from_single`], but you can also define
44/// `random_triples`, `random_quadruples`, and so on, and `random_triples_from_single`,
45/// `random_quadruples_from_single`, and so on, in your program using the code below. The
46/// documentation for [`random_pairs`] and [`random_pairs_from_single`] describes these other
47/// functions as well.
48///
49/// See usage examples [here](self#random_pairs) and [here](self#random_pairs_from_single).
50///
51/// ```
52/// use malachite_base::random::Seed;
53/// use malachite_base::random_tuples;
54/// use malachite_base::tuples::random::next_helper;
55///
56/// random_tuples!(
57/// (pub(crate)),
58/// RandomTriples,
59/// RandomTriplesFromSingle,
60/// random_triples,
61/// random_triples_from_single,
62/// (I::Item, I::Item, I::Item),
63/// [0, X, I, xs, xs_gen],
64/// [1, Y, J, ys, ys_gen],
65/// [2, Z, K, zs, zs_gen]
66/// );
67/// random_tuples!(
68/// (pub(crate)),
69/// RandomQuadruples,
70/// RandomQuadruplesFromSingle,
71/// random_quadruples,
72/// random_quadruples_from_single,
73/// (I::Item, I::Item, I::Item, I::Item),
74/// [0, X, I, xs, xs_gen],
75/// [1, Y, J, ys, ys_gen],
76/// [2, Z, K, zs, zs_gen],
77/// [3, W, L, ws, ws_gen]
78/// );
79/// random_tuples!(
80/// (pub(crate)),
81/// RandomQuintuples,
82/// RandomQuintuplesFromSingle,
83/// random_quintuples,
84/// random_quintuples_from_single,
85/// (I::Item, I::Item, I::Item, I::Item, I::Item),
86/// [0, X, I, xs, xs_gen],
87/// [1, Y, J, ys, ys_gen],
88/// [2, Z, K, zs, zs_gen],
89/// [3, W, L, ws, ws_gen],
90/// [4, V, M, vs, vs_gen]
91/// );
92/// random_tuples!(
93/// (pub(crate)),
94/// RandomSextuples,
95/// RandomSextuplesFromSingle,
96/// random_sextuples,
97/// random_sextuples_from_single,
98/// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item),
99/// [0, X, I, xs, xs_gen],
100/// [1, Y, J, ys, ys_gen],
101/// [2, Z, K, zs, zs_gen],
102/// [3, W, L, ws, ws_gen],
103/// [4, V, M, vs, vs_gen],
104/// [5, U, N, us, us_gen]
105/// );
106/// random_tuples!(
107/// (pub(crate)),
108/// RandomSeptuples,
109/// RandomSeptuplesFromSingle,
110/// random_septuples,
111/// random_septuples_from_single,
112/// (
113/// I::Item,
114/// I::Item,
115/// I::Item,
116/// I::Item,
117/// I::Item,
118/// I::Item,
119/// I::Item
120/// ),
121/// [0, X, I, xs, xs_gen],
122/// [1, Y, J, ys, ys_gen],
123/// [2, Z, K, zs, zs_gen],
124/// [3, W, L, ws, ws_gen],
125/// [4, V, M, vs, vs_gen],
126/// [5, U, N, us, us_gen],
127/// [6, T, O, ts, ts_gen]
128/// );
129/// random_tuples!(
130/// (pub(crate)),
131/// RandomOctuples,
132/// RandomOctuplesFromSingle,
133/// random_octuples,
134/// random_octuples_from_single,
135/// (
136/// I::Item,
137/// I::Item,
138/// I::Item,
139/// I::Item,
140/// I::Item,
141/// I::Item,
142/// I::Item,
143/// I::Item
144/// ),
145/// [0, X, I, xs, xs_gen],
146/// [1, Y, J, ys, ys_gen],
147/// [2, Z, K, zs, zs_gen],
148/// [3, W, L, ws, ws_gen],
149/// [4, V, M, vs, vs_gen],
150/// [5, U, N, us, us_gen],
151/// [6, T, O, ts, ts_gen],
152/// [7, S, P, ss, ss_gen]
153/// );
154/// ```
155#[macro_export]
156macro_rules! random_tuples {
157 (
158 ($($vis:tt)*),
159 $random_struct: ident,
160 $random_struct_from_single: ident,
161 $random_fn: ident,
162 $random_fn_from_single: ident,
163 $single_out: tt,
164 $([$i: expr, $t: ident, $it: ident, $xs: ident, $xs_gen:ident]),*
165 ) => {
166 /// This documentation applies not only to `RandomPairs`, but also to `RandomTriples`,
167 /// `RandomQuadruples`, and so on. See [`random_tuples`] for more information.
168 ///
169 /// Generates random $n$-tuples using elements from $n$ iterators.
170 #[derive(Clone, Debug)]
171 #[allow(dead_code)]
172 $($vis)* struct $random_struct<$($t: Clone, $it: Iterator<Item = $t>,)*> {
173 $($xs: $it,)*
174 }
175
176 impl<$($t: Clone, $it: Iterator<Item = $t>,)*> Iterator for $random_struct<$($t, $it,)*>
177 {
178 type Item = ($($t,)*);
179
180 #[inline]
181 fn next(&mut self) -> Option<Self::Item> {
182 Some(($(self.$xs.next().unwrap()),*))
183 }
184 }
185
186 /// This documentation applies not only to `random_pairs`, but also to `random_triples`,
187 /// `random_quadruples`, and so on. See [`random_tuples`] for more information.
188 ///
189 /// Generates random $n$-tuples with elements from $n$ iterators.
190 ///
191 /// The probability of a particular $n$-tuple being generated is the product of the
192 /// probabilities of each of its elements.
193 ///
194 /// `xs`, `ys`, `zs`, ... must be infinite.
195 ///
196 /// # Examples
197 /// See [here](self#random_pairs).
198 #[allow(dead_code)]
199 $($vis)* fn $random_fn<$($t: Clone, $it: Iterator<Item = $t>,)*>(
200 seed: Seed,
201 $($xs_gen: &dyn Fn(Seed) -> $it,)*
202 ) -> $random_struct<$($t, $it,)*> {
203 $random_struct {
204 $($xs: $xs_gen(seed.fork(stringify!($xs))),)*
205 }
206 }
207
208 /// This documentation applies not only to `RandomPairsFromSingle`, but also to
209 /// `RandomTriplesFromSingle`, `RandomQuadruplesFromSingle`, and so on. See
210 /// [`random_tuples`] for more information.
211 ///
212 /// Generates random $n$-tuples using elements from a single iterator.
213 #[derive(Clone, Debug)]
214 #[allow(dead_code)]
215 $($vis)* struct $random_struct_from_single<I: Iterator> {
216 xs: I
217 }
218
219 impl<I: Iterator> Iterator for $random_struct_from_single<I> {
220 type Item = $single_out;
221
222 #[inline]
223 fn next(&mut self) -> Option<$single_out> {
224 Some(($(next_helper(&mut self.xs, $i).unwrap(),)*))
225 }
226 }
227
228 /// This documentation applies not only to `random_pairs_from_single`, but also to
229 /// `random_triples_from_single`, `random_quadruples_from_single`, and so on. See
230 /// [`random_tuples`] for more information.
231 ///
232 /// Generates random $n$-tuples using elements from a single iterator.
233 ///
234 /// The probability of a particular $n$-tuple being generated is the product of the
235 /// probabilities of each of its elements.
236 ///
237 /// `xs` must be infinite.
238 ///
239 /// # Examples
240 /// See [here](self#random_pairs_from_single).
241 #[allow(dead_code)]
242 #[inline]
243 $($vis)* const fn $random_fn_from_single<I: Iterator>(xs: I)
244 -> $random_struct_from_single<I> {
245 $random_struct_from_single { xs }
246 }
247 }
248}
249
250random_tuples!(
251 (pub),
252 RandomPairs,
253 RandomPairsFromSingle,
254 random_pairs,
255 random_pairs_from_single,
256 (I::Item, I::Item),
257 [0, X, I, xs, xs_gen],
258 [1, Y, J, ys, ys_gen]
259);
260
261/// Defines custom random tuple generators.
262///
263/// You can define custom tuple generators like `random_triples_xyx` in your program using the code
264/// below.
265///
266/// See usage examples [here](self#random_triples_xyx).
267///
268/// ```
269/// use malachite_base::random::Seed;
270/// use malachite_base::random_custom_tuples;
271///
272/// random_custom_tuples!(
273/// (pub(crate)),
274/// RandomTriplesXXY,
275/// (X, X, Y),
276/// random_triples_xxy,
277/// [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1]],
278/// [Y, J, ys, ys_gen, [y_2, y_2]]
279/// );
280/// random_custom_tuples!(
281/// (pub(crate)),
282/// RandomTriplesXYX,
283/// (X, Y, X),
284/// random_triples_xyx,
285/// [X, I, xs, xs_gen, [x_0, x_0], [x_2, y_1]],
286/// [Y, J, ys, ys_gen, [y_1, x_2]]
287/// );
288/// random_custom_tuples!(
289/// (pub(crate)),
290/// RandomTriplesXYY,
291/// (X, Y, Y),
292/// random_triples_xyy,
293/// [X, I, xs, xs_gen, [x_0, x_0]],
294/// [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]]
295/// );
296/// random_custom_tuples!(
297/// (pub(crate)),
298/// RandomQuadruplesXXXY,
299/// (X, X, X, Y),
300/// random_quadruples_xxxy,
301/// [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1], [x_2, x_2]],
302/// [Y, J, ys, ys_gen, [y_3, y_3]]
303/// );
304/// random_custom_tuples!(
305/// (pub(crate)),
306/// RandomQuadruplesXXYX,
307/// (X, X, Y, X),
308/// random_quadruples_xxyx,
309/// [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1], [x_3, y_2]],
310/// [Y, J, ys, ys_gen, [y_2, x_3]]
311/// );
312/// random_custom_tuples!(
313/// (pub(crate)),
314/// RandomQuadruplesXXYZ,
315/// (X, X, Y, Z),
316/// random_quadruples_xxyz,
317/// [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1]],
318/// [Y, J, ys, ys_gen, [y_2, y_2]],
319/// [Z, K, zs, zs_gen, [z_3, z_3]]
320/// );
321/// random_custom_tuples!(
322/// (pub(crate)),
323/// RandomQuadruplesXYXZ,
324/// (X, Y, X, Z),
325/// random_quadruples_xyxz,
326/// [X, I, xs, xs_gen, [x_0, x_0], [x_2, y_1]],
327/// [Y, J, ys, ys_gen, [y_1, x_2]],
328/// [Z, K, zs, zs_gen, [z_3, z_3]]
329/// );
330/// random_custom_tuples!(
331/// (pub(crate)),
332/// RandomQuadruplesXYYX,
333/// (X, Y, Y, X),
334/// random_quadruples_xyyx,
335/// [X, I, xs, xs_gen, [x_0, x_0], [x_3, y_1]],
336/// [Y, J, ys, ys_gen, [y_1, y_2], [y_2, x_3]]
337/// );
338/// random_custom_tuples!(
339/// (pub(crate)),
340/// RandomQuadruplesXYYZ,
341/// (X, Y, Y, Z),
342/// random_quadruples_xyyz,
343/// [X, I, xs, xs_gen, [x_0, x_0]],
344/// [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]],
345/// [Z, K, zs, zs_gen, [z_3, z_3]]
346/// );
347/// random_custom_tuples!(
348/// (pub(crate)),
349/// RandomQuadruplesXYZZ,
350/// (X, Y, Z, Z),
351/// random_quadruples_xyzz,
352/// [X, I, xs, xs_gen, [x_0, x_0]],
353/// [Y, J, ys, ys_gen, [y_1, y_1]],
354/// [Z, K, zs, zs_gen, [z_2, z_2], [z_3, z_3]]
355/// );
356/// random_custom_tuples!(
357/// (pub(crate)),
358/// RandomQuintuplesXYYYZ,
359/// (X, Y, Y, Y, Z),
360/// random_quintuples_xyyyz,
361/// [X, I, xs, xs_gen, [x_0, x_0]],
362/// [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2], [y_3, y_3]],
363/// [Z, K, zs, zs_gen, [z_4, z_4]]
364/// );
365/// ```
366#[macro_export]
367macro_rules! random_custom_tuples {
368 (
369 ($($vis:tt)*),
370 $random_struct: ident,
371 $out_t: ty,
372 $random_fn: ident,
373 $([$t: ident, $it: ident, $xs: ident, $xs_gen: ident, $([$x: ident, $x_ord: ident]),*]),*
374 ) => {
375 // Generates random $n$-tuples with elements from $m$ iterators, where $m \leq n$.
376 //
377 // The mapping from iterators to tuple slots is indicated by the struct name; for example,
378 // in `RandomTriplesXYX` there are two iterators, `X`, and `Y`; `X` generates the elements
379 // in the first and third slots of the output triples, and `Y` generates the elements in the
380 // second slots.
381 #[derive(Clone, Debug)]
382 $($vis)* struct $random_struct<$($t: Clone, $it: Iterator<Item = $t>,)*> {
383 $($xs: $it,)*
384 }
385
386 impl<$($t: Clone, $it: Iterator<Item = $t>,)*> Iterator for $random_struct<$($t, $it,)*>
387 {
388 type Item = $out_t;
389
390 fn next(&mut self) -> Option<Self::Item> {
391 $(
392 $(
393 let $x = self.$xs.next().unwrap();
394 )*
395 )*
396 Some(($($($x_ord,)*)*))
397 }
398 }
399
400 // Generates random $n$-tuples with elements from $m$ iterators, where $m \leq n$.
401 //
402 // The mapping from iterators to tuple slots is indicated by the function name; for example,
403 // `random_triples_xyx` takes two iterators, `xs`, and `ys`; `xs` generates the elements in
404 // the first and third slots of the output triples, and `ys` generates the elements in the
405 // second slots.
406 //
407 // The probability of a particular $n$-tuple being generated is the product of the
408 // probabilities of each of its elements.
409 //
410 // `xs`, `ys`, `zs`, ... must be infinite.
411 //
412 // # Examples
413 // See [here](self#random_triples_xyx).
414 $($vis)* fn $random_fn<$($t: Clone, $it: Iterator<Item = $t>,)*>(
415 seed: Seed,
416 $($xs_gen: &dyn Fn(Seed) -> $it,)*
417 ) -> $random_struct<$($t, $it,)*> {
418 $random_struct {
419 $($xs: $xs_gen(seed.fork(stringify!($xs))),)*
420 }
421 }
422 }
423}
424
425/// Generates random pairs using elements from a single iterator, where the first element is less
426/// than the second.
427#[derive(Clone, Debug)]
428pub struct RandomOrderedUniquePairs<I: Iterator>
429where
430 I::Item: Ord,
431{
432 xs: I,
433}
434
435impl<I: Iterator> Iterator for RandomOrderedUniquePairs<I>
436where
437 I::Item: Ord,
438{
439 type Item = (I::Item, I::Item);
440
441 #[inline]
442 fn next(&mut self) -> Option<Self::Item> {
443 let mut out_0 = None;
444 let out_1;
445 loop {
446 let x = self.xs.next().unwrap();
447 if out_0.is_none() {
448 out_0 = Some(x);
449 } else {
450 match x.cmp(out_0.as_ref().unwrap()) {
451 Equal => {}
452 Greater => {
453 out_1 = x;
454 break;
455 }
456 Less => {
457 out_1 = out_0.unwrap();
458 out_0 = Some(x);
459 break;
460 }
461 }
462 }
463 }
464 Some((out_0.unwrap(), out_1))
465 }
466}
467
468/// Generates random pairs using elements from a single iterator, where the first element of each
469/// pair is less than the second.
470///
471/// The input iterator must generate at least two distinct elements; otherwise, this iterator will
472/// hang.
473///
474/// $$
475/// P((x\_0, x\_1)) = 2P(x\_0)P(x\_1).
476/// $$
477///
478/// The above formula assumes that the pair is valid, \emph{i.e.} its first element is less than its
479/// second. The probability of an invalid pair is zero.
480///
481/// `xs` must be infinite.
482///
483/// # Expected complexity per iteration
484/// $T(i) = O(T^\prime(i))$
485///
486/// $M(i) = O(M^\prime(i))$
487///
488/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, and $T^\prime$ and
489/// $M^\prime$ are the time and memory functions of `xs`: each pair requires an expected constant
490/// number of draws, though duplicate draws force retries, and the iterator hangs if `xs` cannot
491/// produce two distinct values.
492#[inline]
493pub const fn random_ordered_unique_pairs<I: Iterator>(xs: I) -> RandomOrderedUniquePairs<I>
494where
495 I::Item: Ord,
496{
497 RandomOrderedUniquePairs { xs }
498}
499
500/// Defines random ordered unique tuple generators.
501///
502/// Malachite provides [`random_ordered_unique_pairs`], but you can also define
503/// `random_ordered_unique_triples`, `random_ordered_unique_quadruples`, and so on, in your program
504/// using the code below.
505///
506/// See usage examples [here](self#random_ordered_unique_quadruples).
507///
508/// ```
509/// use malachite_base::random_ordered_unique_tuples;
510/// use malachite_base::sets::random::{
511/// random_b_tree_sets_fixed_length, RandomBTreeSetsFixedLength,
512/// };
513///
514/// random_ordered_unique_tuples!(
515/// (pub(crate)),
516/// RandomOrderedUniqueTriples,
517/// 3,
518/// (I::Item, I::Item, I::Item),
519/// random_ordered_unique_triples,
520/// [0, 1, 2]
521/// );
522/// random_ordered_unique_tuples!(
523/// (pub(crate)),
524/// RandomOrderedUniqueQuadruples,
525/// 4,
526/// (I::Item, I::Item, I::Item, I::Item),
527/// random_ordered_unique_quadruples,
528/// [0, 1, 2, 3]
529/// );
530/// random_ordered_unique_tuples!(
531/// (pub(crate)),
532/// RandomOrderedUniqueQuintuples,
533/// 5,
534/// (I::Item, I::Item, I::Item, I::Item, I::Item),
535/// random_ordered_unique_quintuples,
536/// [0, 1, 2, 3, 4]
537/// );
538/// random_ordered_unique_tuples!(
539/// (pub(crate)),
540/// RandomOrderedUniqueSextuples,
541/// 6,
542/// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item),
543/// random_ordered_unique_sextuples,
544/// [0, 1, 2, 3, 4, 5]
545/// );
546/// random_ordered_unique_tuples!(
547/// (pub(crate)),
548/// RandomOrderedUniqueSeptuples,
549/// 7,
550/// (
551/// I::Item,
552/// I::Item,
553/// I::Item,
554/// I::Item,
555/// I::Item,
556/// I::Item,
557/// I::Item
558/// ),
559/// random_ordered_unique_septuples,
560/// [0, 1, 2, 3, 4, 5, 6]
561/// );
562/// random_ordered_unique_tuples!(
563/// (pub(crate)),
564/// RandomOrderedUniqueOctuples,
565/// 8,
566/// (
567/// I::Item,
568/// I::Item,
569/// I::Item,
570/// I::Item,
571/// I::Item,
572/// I::Item,
573/// I::Item,
574/// I::Item
575/// ),
576/// random_ordered_unique_octuples,
577/// [0, 1, 2, 3, 4, 5, 6, 7]
578/// );
579/// ```
580#[macro_export]
581macro_rules! random_ordered_unique_tuples {
582 (
583 ($($vis:tt)*),
584 $struct: ident,
585 $k: expr,
586 $out_t: ty,
587 $fn: ident,
588 [$($i: expr),*]
589 ) => {
590 // Generates random $n$-tuples using elements from a single iterator, where the tuples have
591 // no repeated elements, and the elements are in ascending order.
592 #[derive(Clone, Debug)]
593 $($vis)* struct $struct<I: Iterator> where I::Item: Ord {
594 xs: RandomBTreeSetsFixedLength<I>,
595 }
596
597 impl<I: Iterator> Iterator for $struct<I> where I::Item: Ord {
598 type Item = $out_t;
599
600 #[inline]
601 fn next(&mut self) -> Option<Self::Item> {
602 let mut elements = self.xs.next().unwrap().into_iter();
603 Some(($(((elements.next().unwrap(), $i).0)),*))
604 }
605 }
606
607 // Generates random $n$-tuples using elements from a single iterator, where the tuples have
608 // no repeated elements, and the elements are in ascending order.
609 //
610 // The input iterator must generate at least `len` distinct elements; otherwise, this
611 // iterator will hang.
612 //
613 // $$
614 // P((x\_i)\_{i=0}^{n-1}) = n!\prod\_{i=0}^{n-1}P(x\_i).
615 // $$
616 //
617 // The above formula assumes that the tuple is valid, \emph{i.e.} its elements are strictly
618 // increasing. The probability of an invalid tuple is zero.
619 //
620 // `xs` must be infinite.
621 //
622 // # Examples
623 // See [here](self#random_ordered_unique_quadruples).
624 #[inline]
625 $($vis)* fn $fn<I: Iterator>(xs: I) -> $struct<I>
626 where
627 I::Item: Ord,
628 {
629 $struct {
630 xs: random_b_tree_sets_fixed_length($k, xs),
631 }
632 }
633 }
634}
635
636/// Generates random pairs using elements from a single iterator, where the first element is not
637/// equal to the second.
638#[derive(Clone, Debug)]
639pub struct RandomUniquePairs<I: Iterator>
640where
641 I::Item: Eq,
642{
643 xs: I,
644}
645
646impl<I: Iterator> Iterator for RandomUniquePairs<I>
647where
648 I::Item: Eq,
649{
650 type Item = (I::Item, I::Item);
651
652 #[inline]
653 fn next(&mut self) -> Option<Self::Item> {
654 let mut out_0 = None;
655 let out_1;
656 loop {
657 let x = self.xs.next().unwrap();
658 if let Some(out_0) = out_0.as_ref() {
659 if x != *out_0 {
660 out_1 = x;
661 break;
662 }
663 } else {
664 out_0 = Some(x);
665 }
666 }
667 Some((out_0.unwrap(), out_1))
668 }
669}
670
671/// Generates random pairs using elements from a single iterator, where the two elements of each
672/// pair are unequal.
673///
674/// The input iterator must generate at least two distinct elements; otherwise, this iterator will
675/// hang.
676///
677/// `xs` must be infinite.
678///
679/// # Expected complexity per iteration
680/// $T(i) = O(T^\prime(i))$
681///
682/// $M(i) = O(M^\prime(i))$
683///
684/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, and $T^\prime$ and
685/// $M^\prime$ are the time and memory functions of `xs`: each pair requires an expected constant
686/// number of draws, though duplicate draws force retries, and the iterator hangs if `xs` cannot
687/// produce two distinct values.
688#[inline]
689pub const fn random_unique_pairs<I: Iterator>(xs: I) -> RandomUniquePairs<I>
690where
691 I::Item: Eq,
692{
693 RandomUniquePairs { xs }
694}
695
696/// Defines random unique tuple generators.
697///
698/// Malachite provides [`random_unique_pairs`], but you can also define `random_unique_triples`,
699/// `random_unique_quadruples`, and so on, in your program using the code below.
700///
701/// See usage examples [here](self#random_unique_quadruples).
702///
703/// ```
704/// use malachite_base::random_unique_tuples;
705/// use std::collections::HashMap;
706/// use std::hash::Hash;
707///
708/// random_unique_tuples!(
709/// (pub(crate)),
710/// RandomOrderedUniqueTriples,
711/// 3,
712/// (I::Item, I::Item, I::Item),
713/// random_unique_triples,
714/// [0, 1, 2]
715/// );
716/// random_unique_tuples!(
717/// (pub(crate)),
718/// RandomOrderedUniqueQuadruples,
719/// 4,
720/// (I::Item, I::Item, I::Item, I::Item),
721/// random_unique_quadruples,
722/// [0, 1, 2, 3]
723/// );
724/// random_unique_tuples!(
725/// (pub(crate)),
726/// RandomOrderedUniqueQuintuples,
727/// 5,
728/// (I::Item, I::Item, I::Item, I::Item, I::Item),
729/// random_unique_quintuples,
730/// [0, 1, 2, 3, 4]
731/// );
732/// random_unique_tuples!(
733/// (pub(crate)),
734/// RandomOrderedUniqueSextuples,
735/// 6,
736/// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item),
737/// random_unique_sextuples,
738/// [0, 1, 2, 3, 4, 5]
739/// );
740/// random_unique_tuples!(
741/// (pub(crate)),
742/// RandomOrderedUniqueSeptuples,
743/// 7,
744/// (
745/// I::Item,
746/// I::Item,
747/// I::Item,
748/// I::Item,
749/// I::Item,
750/// I::Item,
751/// I::Item
752/// ),
753/// random_unique_septuples,
754/// [0, 1, 2, 3, 4, 5, 6]
755/// );
756/// random_unique_tuples!(
757/// (pub(crate)),
758/// RandomOrderedUniqueOctuples,
759/// 8,
760/// (
761/// I::Item,
762/// I::Item,
763/// I::Item,
764/// I::Item,
765/// I::Item,
766/// I::Item,
767/// I::Item,
768/// I::Item
769/// ),
770/// random_unique_octuples,
771/// [0, 1, 2, 3, 4, 5, 6, 7]
772/// );
773/// ```
774#[macro_export]
775macro_rules! random_unique_tuples {
776 (
777 ($($vis:tt)*),
778 $struct: ident,
779 $k: expr,
780 $out_t: ty,
781 $fn: ident,
782 [$($i: tt),*]
783 ) => {
784 #[derive(Clone, Debug)]
785 $($vis)* struct $struct<I: Iterator> where I::Item: Eq + Hash {
786 xs: I,
787 }
788
789 impl<I: Iterator> Iterator for $struct<I> where I::Item: Eq + Hash {
790 type Item = $out_t;
791
792 #[inline]
793 fn next(&mut self) -> Option<Self::Item> {
794 let mut xs_to_indices = HashMap::with_capacity($k);
795 let mut i = 0;
796 while i < $k {
797 xs_to_indices
798 .entry(self.xs.next().unwrap())
799 .or_insert_with(|| {
800 i += 1;
801 i - 1
802 });
803 }
804 let mut out = ($((None, $i).0),*);
805 for (x, i) in xs_to_indices {
806 match i {
807 $($i => {out.$i = Some(x)},)*
808 _ => {}
809 }
810 }
811 Some(($(out.$i.unwrap()),*))
812 }
813 }
814
815 #[inline]
816 $($vis)* fn $fn<I: Iterator>(xs: I) -> $struct<I> where I::Item: Eq + Hash,
817 {
818 $struct { xs }
819 }
820 }
821}