// Copyright © 2024 Mikhail Hogrefe // // This file is part of Malachite. // // Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU // Lesser General Public License (LGPL) as published by the Free Software Foundation; either version // 3 of the License, or (at your option) any later version. See . use itertools::Itertools; use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; use malachite_base::iterators::iterator_cache::IteratorCache; use malachite_base::num::arithmetic::traits::CheckedPow; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::iterators::{ruler_sequence, RulerSequence}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::num::random::{random_unsigned_range, RandomUnsignedRange}; use malachite_base::random::Seed; use malachite_base::sets::random::{random_b_tree_sets_fixed_length, RandomBTreeSetsFixedLength}; use malachite_base::tuples::exhaustive::{ clone_helper, exhaustive_dependent_pairs, ExhaustiveDependentPairs, }; use malachite_base::tuples::random::next_helper; use malachite_base::unions::UnionFromStrError; use malachite_base::vecs::exhaustive::{ exhaustive_ordered_unique_vecs_fixed_length, fixed_length_ordered_unique_indices_helper, next_bit_pattern, unique_indices, validate_oi_map, ExhaustiveOrderedUniqueCollections, ExhaustiveUniqueVecsGenerator, LexFixedLengthVecsOutput, UniqueIndices, }; use malachite_base::vecs::ExhaustiveVecPermutations; use std::cmp::max; use std::collections::HashMap; use std::fmt::{self, Display, Formatter}; use std::hash::Hash; use std::marker::PhantomData; use std::str::FromStr; fn unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { (a.unwrap(), b.unwrap(), c.unwrap()) } lex_custom_tuples! { (pub(crate)), LexTriplesXXY, (X, X, Y), (None, None, None), unwrap_triple, lex_triples_xxy, [X, I, xs, [0, x_0], [1, x_1]], [Y, J, ys, [2, y_2]] } lex_custom_tuples!( (pub(crate)), LexTriplesXYX, (X, Y, X), (None, None, None), unwrap_triple, lex_triples_xyx, [X, I, xs, [0, x_0], [2, x_2]], [Y, J, ys, [1, y_1]] ); lex_tuples!( (pub(crate)), 3, LexTriples, LexTriplesFromSingle, lex_triples, lex_triples_from_single, (T, T, T), [0, X, I, xs, x], [1, Y, J, ys, y], [2, Z, K, zs, z] ); lex_tuples!( (pub(crate)), 4, LexQuadruples, LexQuadruplesFromSingle, lex_quadruples, lex_quadruples_from_single, (T, T, T, T), [0, X, I, xs, x], [1, Y, J, ys, y], [2, Z, K, zs, z], [3, W, L, ws, w] ); lex_tuples!( (pub(crate)), 5, LexQuintuples, LexQuintuplesFromSingle, lex_quintuples, lex_quintuples_from_single, (T, T, T, T, T), [0, X, I, xs, x], [1, Y, J, ys, y], [2, Z, K, zs, z], [3, W, L, ws, w], [4, V, M, vs, v] ); lex_tuples!( (pub(crate)), 8, LexOctuples, LexOctuplesFromSingle, lex_octuples, lex_octuples_from_single, (T, T, T, T, T, T, T, T), [0, X, I, xs, x], [1, Y, J, ys, y], [2, Z, K, zs, z], [3, W, L, ws, w], [4, V, M, vs, v], [5, U, N, us, u], [6, T, O, ts, t], [7, S, P, ss, s] ); exhaustive_tuples_1_input!( (pub(crate)), ExhaustiveTriples1Input, exhaustive_triples_1_input, exhaustive_triples_from_single, (I::Item, I::Item, I::Item), [0, output_type_x], [1, output_type_y], [2, output_type_z] ); exhaustive_tuples_1_input!( (pub(crate)), ExhaustiveQuadruples1Input, exhaustive_quadruples_1_input, exhaustive_quadruples_from_single, (I::Item, I::Item, I::Item, I::Item), [0, output_type_x], [1, output_type_y], [2, output_type_z], [3, output_type_w] ); exhaustive_tuples_1_input!( (pub(crate)), ExhaustiveQuintuples1Input, exhaustive_quintuples_1_input, exhaustive_quintuples_from_single, (I::Item, I::Item, I::Item, I::Item, I::Item), [0, output_type_x], [1, output_type_y], [2, output_type_z], [3, output_type_w], [4, output_type_v] ); exhaustive_tuples_1_input!( (pub(crate)), ExhaustiveOctuples1Input, exhaustive_octuples_1_input, exhaustive_octuples_from_single, ( I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item ), [0, output_type_x], [1, output_type_y], [2, output_type_z], [3, output_type_w], [4, output_type_v], [5, output_type_u], [6, output_type_t], [7, output_type_s] ); custom_tuples!( (pub(crate)), ExhaustiveTriplesXXY, (X, X, Y), (None, None, None), unwrap_triple, exhaustive_triples_xxy, exhaustive_triples_xxy_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0], [1, output_type_xs_1]], [Y, J, ys, ys_done, [2, output_type_ys_2]] ); custom_tuples!( (pub(crate)), ExhaustiveTriplesXYX, (X, Y, X), (None, None, None), unwrap_triple, exhaustive_triples_xyx, exhaustive_triples_xyx_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0], [2, output_type_ys_1]], [Y, J, ys, ys_done, [1, output_type_xs_2]] ); lex_ordered_unique_tuples!( (pub(crate)), LexOrderedUniqueTriples, 3, (I::Item, I::Item, I::Item), lex_ordered_unique_triples, [0, 1, 2] ); lex_ordered_unique_tuples!( (pub(crate)), LexOrderedUniqueQuadruples, 4, (I::Item, I::Item, I::Item, I::Item), lex_ordered_unique_quadruples, [0, 1, 2, 3] ); lex_ordered_unique_tuples!( (pub(crate)), LexOrderedUniqueQuintuples, 5, (I::Item, I::Item, I::Item, I::Item, I::Item), lex_ordered_unique_quintuples, [0, 1, 2, 3, 4] ); exhaustive_ordered_unique_tuples!( (pub(crate)), ExhaustiveOrderedUniqueTriples, 3, (I::Item, I::Item, I::Item), exhaustive_ordered_unique_triples, [0, 1, 2] ); exhaustive_ordered_unique_tuples!( (pub(crate)), ExhaustiveOrderedUniqueQuadruples, 4, (I::Item, I::Item, I::Item, I::Item), exhaustive_ordered_unique_quadruples, [0, 1, 2, 3] ); exhaustive_ordered_unique_tuples!( (pub(crate)), ExhaustiveOrderedUniqueQuintuples, 5, (I::Item, I::Item, I::Item, I::Item, I::Item), exhaustive_ordered_unique_quintuples, [0, 1, 2, 3, 4] ); lex_unique_tuples!( (pub(crate)), LexUniqueTriples, 3, (I::Item, I::Item, I::Item), lex_unique_triples, [0, 1, 2] ); lex_unique_tuples!( (pub(crate)), LexUniqueQuadruples, 4, (I::Item, I::Item, I::Item, I::Item), lex_unique_quadruples, [0, 1, 2, 3] ); lex_unique_tuples!( (pub(crate)), LexUniqueQuintuples, 5, (I::Item, I::Item, I::Item, I::Item, I::Item), lex_unique_quintuples, [0, 1, 2, 3, 4] ); exhaustive_unique_tuples!( (pub(crate)), ExhaustiveUniqueTriples, 3, (I::Item, I::Item, I::Item), exhaustive_unique_triples, [0, 1, 2] ); exhaustive_unique_tuples!( (pub(crate)), ExhaustiveUniqueQuadruples, 4, (I::Item, I::Item, I::Item, I::Item), exhaustive_unique_quadruples, [0, 1, 2, 3] ); exhaustive_unique_tuples!( (pub(crate)), ExhaustiveUniqueQuintuples, 5, (I::Item, I::Item, I::Item, I::Item, I::Item), exhaustive_unique_quintuples, [0, 1, 2, 3, 4] ); random_tuples!( (pub(crate)), RandomTriples, RandomTriplesFromSingle, random_triples, random_triples_from_single, (I::Item, I::Item, I::Item), [0, X, I, xs, xs_gen], [1, Y, J, ys, ys_gen], [2, Z, K, zs, zs_gen] ); random_custom_tuples!( (pub(crate)), RandomTriplesXXY, (X, X, Y), random_triples_xxy, [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1]], [Y, J, ys, ys_gen, [y_2, y_2]] ); random_custom_tuples!( (pub(crate)), RandomTriplesXYX, (X, Y, X), random_triples_xyx, [X, I, xs, xs_gen, [x_0, x_0], [x_2, y_1]], [Y, J, ys, ys_gen, [y_1, x_2]] ); random_ordered_unique_tuples!( (pub(crate)), RandomOrderedUniqueTriples, 3, (I::Item, I::Item, I::Item), random_ordered_unique_triples, [0, 1, 2] ); random_unique_tuples!( (pub(crate)), RandomUniqueTriples, 3, (I::Item, I::Item, I::Item), random_unique_triples, [0, 1, 2] ); exhaustive_unions!( (pub(crate)), Union3, LexUnion3s, ExhaustiveUnion3s, lex_union3s, exhaustive_union3s, 3, [0, X, I, A, xs, xs_done], [1, Y, J, B, ys, ys_done], [2, Z, K, C, zs, zs_done] ); union_struct!( (pub(crate)), Union3, Union3, [A, A, 'A', a], [B, B, 'B', b], [C, C, 'C', c] ); random_unions!( (pub(crate)), Union3, RandomUnion3s, random_union3s, 3, [0, X, I, A, xs, xs_gen], [1, Y, J, B, ys, ys_gen], [2, Z, K, C, zs, zs_gen] ); lex_vecs_fixed_length!( (pub(crate)), LexFixedLengthVecs3Inputs, lex_vecs_fixed_length_3_inputs, lex_vecs_length_3, [0, I, xs, xs_outputs], [1, J, ys, ys_outputs], [2, K, zs, zs_outputs] ); exhaustive_vecs_fixed_length!( (pub(crate)), ExhaustiveFixedLengthVecs3Inputs, exhaustive_vecs_fixed_length_3_inputs, exhaustive_vecs_length_3, [0, I, xs, xs_done, xs_outputs], [1, J, ys, ys_done, ys_outputs], [2, K, zs, zs_done, zs_outputs] ); random_vecs_fixed_length!( (pub(crate)), RandomFixedLengthVecs3Inputs, random_vecs_fixed_length_3_inputs, random_vecs_length_3, [0, I, xs, xs_gen], [1, J, ys, ys_gen], [2, K, zs, zs_gen] );